mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
[Haik]: refactor: migrate frontend from flat file structure to nested AppShell architecture — moves DynamicIsland under TitleBar with CompactPill/ExpandedCard subgroups, consolidates Settings and Commands pages into AppShell/components with dedicated components/hooks/shared dirs, relocates Layout pieces (Sidebar, TitleBar, UpdateBanner) as AppShell children, and updates Main.tsx import path
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
setUpdateDownloaded,
|
||||
setUpdateError,
|
||||
} from '@/shared/state/updateSlice';
|
||||
import AppShell from './components/Layout/AppShell';
|
||||
import AppShell from './components/AppShell/AppShell';
|
||||
import Dashboard from './pages/Dashboard/Dashboard';
|
||||
import DashboardSelection from './pages/DashboardSelection/DashboardSelection';
|
||||
import Skills from './pages/Skills/Skills';
|
||||
|
||||
+4
-4
@@ -6,7 +6,7 @@ import Snackbar from '@mui/material/Snackbar';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import RestartAltIcon from '@mui/icons-material/RestartAlt';
|
||||
import SystemUpdateAltIcon from '@mui/icons-material/SystemUpdateAlt';
|
||||
import Settings from '@/app/pages/Settings/Settings';
|
||||
import Settings from './components/Settings/Settings';
|
||||
import { useAppDispatch, useAppSelector } from '@/shared/hooks';
|
||||
import { LIST_DASHBOARDS } from '@/shared/backend-bridge/apps/dashboards';
|
||||
import { LIST_APPS } from '@/shared/backend-bridge/apps/app_builder';
|
||||
@@ -14,9 +14,9 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { useUpdateNotification } from './hooks/useUpdateNotification';
|
||||
import { useSidebarResize } from './hooks/useSidebarResize';
|
||||
import { useUrlInterception } from './hooks/useUrlInterception';
|
||||
import TitleBar from './TitleBar';
|
||||
import Sidebar from './Sidebar';
|
||||
import UpdateBanner from './UpdateBanner';
|
||||
import TitleBar from './components/TitleBar/TitleBar';
|
||||
import Sidebar from './components/Sidebar';
|
||||
import UpdateBanner from './components/UpdateBanner';
|
||||
|
||||
const AppShell: React.FC = () => {
|
||||
const c = useClaudeTokens();
|
||||
+4
-4
@@ -13,10 +13,10 @@ import Snackbar from '@mui/material/Snackbar';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import SaveIcon from '@mui/icons-material/Save';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { CommandsContent } from '@/app/pages/Commands/Commands';
|
||||
import { CommandsTab } from './components/CommandsTab/CommandsTab';
|
||||
import { useSettings } from './hooks/useSettings';
|
||||
import GeneralTab from './GeneralTab';
|
||||
import ModelsTab from './ModelsTab';
|
||||
import GeneralTab from './components/GeneralTab/GeneralTab';
|
||||
import ModelsTab from './components/ModelsTab/ModelsTab';
|
||||
|
||||
const Settings: React.FC = () => {
|
||||
const s = useSettings();
|
||||
@@ -93,7 +93,7 @@ const Settings: React.FC = () => {
|
||||
<ModelsTab s={s} />
|
||||
) : (
|
||||
<Box sx={{ pt: 2.5, pb: 1, animation: 'fadeIn 0.2s ease', '@keyframes fadeIn': { from: { opacity: 0 }, to: { opacity: 1 } } }}>
|
||||
<CommandsContent />
|
||||
<CommandsTab />
|
||||
</Box>
|
||||
)}
|
||||
</DialogContent>
|
||||
+4
-4
@@ -2,11 +2,11 @@ import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { useCommands } from './hooks/useCommands';
|
||||
import SlashCommandsSection from './SlashCommandsSection';
|
||||
import AtCommandsSection from './AtCommandsSection';
|
||||
import ShortcutsSection from './ShortcutsSection';
|
||||
import SlashCommandsSection from './components/SlashCommandsSection';
|
||||
import AtCommandsSection from './components/AtCommandsSection';
|
||||
import ShortcutsSection from './components/ShortcutsSection';
|
||||
|
||||
export const CommandsContent: React.FC = () => {
|
||||
export const CommandsTab: React.FC = () => {
|
||||
const c = useClaudeTokens();
|
||||
const { slashCommands, atCommands, modesMap, navShortcuts, actionShortcuts } = useCommands();
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import AlternateEmailIcon from '@mui/icons-material/AlternateEmail';
|
||||
import { SectionHeader } from './CommandsHelpers';
|
||||
import { AtCommand } from './commandsTypes';
|
||||
import { SectionHeader } from './shared/CommandsHelpers';
|
||||
import { AtCommand } from './shared/commandsTypes';
|
||||
|
||||
interface AtCommandsSectionProps {
|
||||
atCommands: AtCommand[];
|
||||
+2
-2
@@ -2,8 +2,8 @@ import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import KeyboardIcon from '@mui/icons-material/Keyboard';
|
||||
import { KeyBadge, SectionHeader } from './CommandsHelpers';
|
||||
import { Shortcut, SHORTCUTS } from './commandsTypes';
|
||||
import { KeyBadge, SectionHeader } from './shared/CommandsHelpers';
|
||||
import { Shortcut, SHORTCUTS } from './shared/commandsTypes';
|
||||
|
||||
interface ShortcutsSectionProps {
|
||||
navShortcuts: Shortcut[];
|
||||
+2
-2
@@ -5,8 +5,8 @@ import Chip from '@mui/material/Chip';
|
||||
import PsychologyIcon from '@mui/icons-material/Psychology';
|
||||
import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined';
|
||||
import TerminalIcon from '@mui/icons-material/Terminal';
|
||||
import { SectionHeader } from './CommandsHelpers';
|
||||
import { SlashCommand } from './commandsTypes';
|
||||
import { SectionHeader } from './shared/CommandsHelpers';
|
||||
import { SlashCommand } from './shared/commandsTypes';
|
||||
|
||||
interface SlashCommandsSectionProps {
|
||||
slashCommands: SlashCommand[];
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { getToolGroupIcon } from '@/app/pages/_shared/getToolGroupIcon';
|
||||
import { LIST_APPS } from '@/shared/backend-bridge/apps/app_builder';
|
||||
import { LIST_SKILLS } from '@/shared/backend-bridge/apps/skills';
|
||||
import { LIST_MODES } from '@/shared/state/modesSlice';
|
||||
import { SlashCommand, AtCommand, SHORTCUTS } from '../commandsTypes';
|
||||
import { SlashCommand, AtCommand, SHORTCUTS } from '../components/shared/commandsTypes';
|
||||
|
||||
export function useCommands() {
|
||||
const dispatch = useAppDispatch();
|
||||
+3
-3
@@ -12,9 +12,9 @@ import LanguageIcon from '@mui/icons-material/Language';
|
||||
import RestartAltIcon from '@mui/icons-material/RestartAlt';
|
||||
import { RESET_SYSTEM_PROMPT } from '@/shared/backend-bridge/apps/settings';
|
||||
import { DEFAULT_SYSTEM_PROMPT } from '@/shared/state/settingsSlice';
|
||||
import InterfaceSection from './InterfaceSection';
|
||||
import AboutSection from './AboutSection';
|
||||
import type { UseSettingsReturn } from './hooks/useSettings';
|
||||
import InterfaceSection from './components/InterfaceSection';
|
||||
import AboutSection from './components/AboutSection';
|
||||
import type { UseSettingsReturn } from '../../hooks/useSettings';
|
||||
|
||||
const GeneralTab: React.FC<{ s: UseSettingsReturn }> = ({ s }) => {
|
||||
const { form, setForm, c, dispatch, modesList, browseFolder,
|
||||
+1
-1
@@ -8,7 +8,7 @@ import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
|
||||
import LightModeIcon from '@mui/icons-material/LightMode';
|
||||
import DarkModeIcon from '@mui/icons-material/DarkMode';
|
||||
import KeyboardIcon from '@mui/icons-material/Keyboard';
|
||||
import type { UseSettingsReturn } from './hooks/useSettings';
|
||||
import type { UseSettingsReturn } from '../../../hooks/useSettings';
|
||||
|
||||
const InterfaceSection: React.FC<{ s: UseSettingsReturn }> = ({ s }) => {
|
||||
const { form, setForm, c, recordingShortcut, setRecordingShortcut,
|
||||
+2
-2
@@ -7,8 +7,8 @@ import InputAdornment from '@mui/material/InputAdornment';
|
||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||
import SubscriptionCards from './SubscriptionCards';
|
||||
import type { UseSettingsReturn } from './hooks/useSettings';
|
||||
import SubscriptionCards from './components/SubscriptionCards';
|
||||
import type { UseSettingsReturn } from '../../hooks/useSettings';
|
||||
|
||||
const ModelsTab: React.FC<{ s: UseSettingsReturn }> = ({ s }) => {
|
||||
const { c, form, setForm, showApiKey, setShowApiKey, fieldSx, labelSx, descSx } = s;
|
||||
+4
-4
@@ -2,10 +2,10 @@ import React, { useMemo, useRef } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { SPRING_LAYOUT, SPRING_BOUNCE } from './islandTypes';
|
||||
import { IdlePill } from './IdlePill';
|
||||
import { CompactPill } from './CompactPill';
|
||||
import { CompactActionablePill } from './CompactActionablePill';
|
||||
import { ExpandedCard } from './ExpandedCard';
|
||||
import { IdlePill } from './components/IdlePill';
|
||||
import { CompactPill } from './components/CompactPill/CompactPill';
|
||||
import { CompactActionablePill } from './components/CompactActionablePill';
|
||||
import { ExpandedCard } from './components/ExpandedCard/ExpandedCard';
|
||||
import { useDynamicIslandData } from './hooks/useDynamicIslandData';
|
||||
import { useDynamicIslandActions } from './hooks/useDynamicIslandActions';
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import { motion } from 'framer-motion';
|
||||
import { parseMcpToolName } from '@/app/pages/AgentChat/toolkit/approvalToolkit/utils';
|
||||
import { useMcpToolMeta } from '@/app/pages/AgentChat/toolkit/approvalToolkit/utils/useMcpToolMeta';
|
||||
import { SPRING_BOUNCE } from './islandTypes';
|
||||
import type { ClaudeTokens } from './islandTypes';
|
||||
import { SPRING_BOUNCE } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
import type { ClaudeTokens } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
import type { ApprovalRequest } from '@/shared/state/agentsSlice';
|
||||
import { Terminal, FileText, FilePen, Search, MessageCircleQuestion, Wrench } from 'lucide-react';
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import type { ClaudeTokens } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export const ActivityIndicator: React.FC<{ c: ClaudeTokens }> = ({ c }) => (
|
||||
<Box
|
||||
sx={{
|
||||
width: 6,
|
||||
height: 6,
|
||||
borderRadius: '50%',
|
||||
bgcolor: c.text.tertiary,
|
||||
flexShrink: 0,
|
||||
animation: 'subtlePulse 2.2s ease-in-out infinite',
|
||||
'@keyframes subtlePulse': {
|
||||
'0%, 100%': { opacity: 0.6, transform: 'scale(1)' },
|
||||
'50%': { opacity: 1, transform: 'scale(1.15)' },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
+3
-3
@@ -2,9 +2,9 @@ import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { motion } from 'framer-motion';
|
||||
import { ActivityIndicator } from './StatusDot';
|
||||
import { SPRING_BOUNCE } from './islandTypes';
|
||||
import type { ClaudeTokens } from './islandTypes';
|
||||
import { ActivityIndicator } from './ActivityIndicator';
|
||||
import { SPRING_BOUNCE } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
import type { ClaudeTokens } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export const CompactPill: React.FC<{
|
||||
c: ClaudeTokens;
|
||||
+2
-2
@@ -6,8 +6,8 @@ import Tooltip from '@mui/material/Tooltip';
|
||||
import StopCircleOutlinedIcon from '@mui/icons-material/StopCircleOutlined';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { StatusDot } from './StatusDot';
|
||||
import { STATUS_CONFIG } from './islandTypes';
|
||||
import type { ClaudeTokens, TrackedAgent } from './islandTypes';
|
||||
import { STATUS_CONFIG } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
import type { ClaudeTokens, TrackedAgent } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export const AgentStatusRow: React.FC<{
|
||||
agent: TrackedAgent;
|
||||
+1
-1
@@ -6,7 +6,7 @@ import Collapse from '@mui/material/Collapse';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
|
||||
import { AgentStatusRow } from './AgentStatusRow';
|
||||
import type { ClaudeTokens, TrackedAgent } from './islandTypes';
|
||||
import type { ClaudeTokens, TrackedAgent } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export const CompletedAgentsList: React.FC<{
|
||||
c: ClaudeTokens;
|
||||
+1
-1
@@ -8,7 +8,7 @@ import { ApprovalRouter } from '@/app/pages/AgentChat/toolkit/approvalToolkit/Ap
|
||||
import { BatchApprovalWrapper } from '@/app/pages/AgentChat/toolkit/approvalToolkit/BatchApprovalWrapper';
|
||||
import { AgentStatusRow } from './AgentStatusRow';
|
||||
import { CompletedAgentsList } from './CompletedAgentsList';
|
||||
import type { ClaudeTokens, SessionApprovalGroup, TrackedAgent } from './islandTypes';
|
||||
import type { ClaudeTokens, SessionApprovalGroup, TrackedAgent } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export const ExpandedCard: React.FC<{
|
||||
c: ClaudeTokens;
|
||||
+3
-20
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import { STATUS_CONFIG } from './islandTypes';
|
||||
import type { ClaudeTokens } from './islandTypes';
|
||||
import { STATUS_CONFIG } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
import type { ClaudeTokens } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export const StatusDot: React.FC<{ status: string; c: ClaudeTokens }> = ({ status, c }) => {
|
||||
const cfg = STATUS_CONFIG[status];
|
||||
@@ -26,21 +26,4 @@ export const StatusDot: React.FC<{ status: string; c: ClaudeTokens }> = ({ statu
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const ActivityIndicator: React.FC<{ c: ClaudeTokens }> = ({ c }) => (
|
||||
<Box
|
||||
sx={{
|
||||
width: 6,
|
||||
height: 6,
|
||||
borderRadius: '50%',
|
||||
bgcolor: c.text.tertiary,
|
||||
flexShrink: 0,
|
||||
animation: 'subtlePulse 2.2s ease-in-out infinite',
|
||||
'@keyframes subtlePulse': {
|
||||
'0%, 100%': { opacity: 0.6, transform: 'scale(1)' },
|
||||
'50%': { opacity: 1, transform: 'scale(1.15)' },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+1
-1
@@ -4,7 +4,7 @@ import Typography from '@mui/material/Typography';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import { motion } from 'framer-motion';
|
||||
import type { ClaudeTokens } from './islandTypes';
|
||||
import type { ClaudeTokens } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export const IdlePill: React.FC<{ c: ClaudeTokens }> = ({ c }) => (
|
||||
<motion.div
|
||||
+1
-1
@@ -8,7 +8,7 @@ import {
|
||||
} from '@/shared/state/agentsSlice';
|
||||
import { HANDLE_APPROVAL, STOP_AGENT } from '@/shared/backend-bridge/apps/agents';
|
||||
import { setPendingFocusAgentId } from '@/shared/state/tempStateSlice';
|
||||
import type { IslandState, SessionApprovalGroup } from '../islandTypes';
|
||||
import type { IslandState, SessionApprovalGroup } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export function useDynamicIslandActions(
|
||||
groups: SessionApprovalGroup[],
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useAppSelector } from '@/shared/hooks';
|
||||
import type { HistorySession } from '@/shared/state/agentsSlice';
|
||||
import type { IslandState, SessionApprovalGroup, TrackedAgent } from '../islandTypes';
|
||||
import type { IslandState, SessionApprovalGroup, TrackedAgent } from '@/app/components/AppShell/components/TitleBar/DynamicIsland/islandTypes';
|
||||
|
||||
export function useDynamicIslandData() {
|
||||
const sessions = useAppSelector((state) => state.agents.sessions);
|
||||
+1
-1
@@ -7,7 +7,7 @@ import Tooltip from '@mui/material/Tooltip';
|
||||
import ViewSidebarOutlinedIcon from '@mui/icons-material/ViewSidebarOutlined';
|
||||
import ArrowBackOutlinedIcon from '@mui/icons-material/ArrowBackOutlined';
|
||||
import ArrowForwardOutlinedIcon from '@mui/icons-material/ArrowForwardOutlined';
|
||||
import DynamicIsland from '@/app/components/DynamicIsland';
|
||||
import DynamicIsland from './DynamicIsland/DynamicIsland';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
|
||||
interface TitleBarProps {
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './DynamicIsland';
|
||||
Reference in New Issue
Block a user