From 122b757fa2db5cb8d878109c65e549a376733f12 Mon Sep 17 00:00:00 2001 From: Valics Lehel Date: Fri, 11 Jul 2025 22:42:22 +0300 Subject: [PATCH] feat: Add project sorting by date option - Added ability to sort projects by name or most recent session activity - Added projectSortOrder state and localStorage persistence - Added UI controls in ToolsSettings to switch between sort modes - Projects with no sessions sort last when sorting by date - Real-time updates when sort preference changes --- src/components/Sidebar.jsx | 69 +++++++++++++++++++++++++++++++- src/components/ToolsSettings.jsx | 57 +++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx index 8c19771..598b093 100755 --- a/src/components/Sidebar.jsx +++ b/src/components/Sidebar.jsx @@ -61,6 +61,7 @@ function Sidebar({ const [additionalSessions, setAdditionalSessions] = useState({}); const [initialSessionsLoaded, setInitialSessionsLoaded] = useState(new Set()); const [currentTime, setCurrentTime] = useState(new Date()); + const [projectSortOrder, setProjectSortOrder] = useState('name'); const [isRefreshing, setIsRefreshing] = useState(false); const [editingSession, setEditingSession] = useState(null); const [editingSessionName, setEditingSessionName] = useState(''); @@ -114,6 +115,45 @@ function Sidebar({ } }, [projects, isLoading]); + // Load project sort order from settings + useEffect(() => { + const loadSortOrder = () => { + try { + const savedSettings = localStorage.getItem('claude-tools-settings'); + if (savedSettings) { + const settings = JSON.parse(savedSettings); + setProjectSortOrder(settings.projectSortOrder || 'name'); + } + } catch (error) { + console.error('Error loading sort order:', error); + } + }; + + // Load initially + loadSortOrder(); + + // Listen for storage changes + const handleStorageChange = (e) => { + if (e.key === 'claude-tools-settings') { + loadSortOrder(); + } + }; + + window.addEventListener('storage', handleStorageChange); + + // Also check periodically when component is focused (for same-tab changes) + const checkInterval = setInterval(() => { + if (document.hasFocus()) { + loadSortOrder(); + } + }, 1000); + + return () => { + window.removeEventListener('storage', handleStorageChange); + clearInterval(checkInterval); + }; + }, []); + const toggleProject = (projectName) => { const newExpanded = new Set(expandedProjects); if (newExpanded.has(projectName)) { @@ -291,6 +331,33 @@ function Sidebar({ return [...initialSessions, ...additional]; }; + // Helper function to get the last activity date for a project + const getProjectLastActivity = (project) => { + const allSessions = getAllSessions(project); + if (allSessions.length === 0) { + return new Date(0); // Return epoch date for projects with no sessions + } + + // Find the most recent session activity + const mostRecentDate = allSessions.reduce((latest, session) => { + const sessionDate = new Date(session.lastActivity); + return sessionDate > latest ? sessionDate : latest; + }, new Date(0)); + + return mostRecentDate; + }; + + // Sort projects based on selected order + const sortedProjects = [...projects].sort((a, b) => { + if (projectSortOrder === 'date') { + // Sort by most recent activity (descending) + return getProjectLastActivity(b) - getProjectLastActivity(a); + } else { + // Sort by name (ascending) + return a.name.localeCompare(b.name); + } + }); + return (
{/* Header */} @@ -499,7 +566,7 @@ function Sidebar({

) : ( - projects.map((project) => { + sortedProjects.map((project) => { const isExpanded = expandedProjects.has(project.name); const isSelected = selectedProject?.name === project.name; diff --git a/src/components/ToolsSettings.jsx b/src/components/ToolsSettings.jsx index da4aae2..7e5295a 100755 --- a/src/components/ToolsSettings.jsx +++ b/src/components/ToolsSettings.jsx @@ -3,7 +3,7 @@ import { Button } from './ui/button'; import { Input } from './ui/input'; import { ScrollArea } from './ui/scroll-area'; import { Badge } from './ui/badge'; -import { X, Plus, Settings, Shield, AlertTriangle, Moon, Sun } from 'lucide-react'; +import { X, Plus, Settings, Shield, AlertTriangle, Moon, Sun, FolderOpen, SortAsc } from 'lucide-react'; import { useTheme } from '../contexts/ThemeContext'; function ToolsSettings({ isOpen, onClose }) { @@ -15,6 +15,7 @@ function ToolsSettings({ isOpen, onClose }) { const [skipPermissions, setSkipPermissions] = useState(false); const [isSaving, setIsSaving] = useState(false); const [saveStatus, setSaveStatus] = useState(null); + const [projectSortOrder, setProjectSortOrder] = useState('name'); // Common tool patterns const commonTools = [ @@ -51,11 +52,13 @@ function ToolsSettings({ isOpen, onClose }) { setAllowedTools(settings.allowedTools || []); setDisallowedTools(settings.disallowedTools || []); setSkipPermissions(settings.skipPermissions || false); + setProjectSortOrder(settings.projectSortOrder || 'name'); } else { // Set defaults setAllowedTools([]); setDisallowedTools([]); setSkipPermissions(false); + setProjectSortOrder('name'); } } catch (error) { console.error('Error loading tool settings:', error); @@ -63,6 +66,7 @@ function ToolsSettings({ isOpen, onClose }) { setAllowedTools([]); setDisallowedTools([]); setSkipPermissions(false); + setProjectSortOrder('name'); } }; @@ -75,6 +79,7 @@ function ToolsSettings({ isOpen, onClose }) { allowedTools, disallowedTools, skipPermissions, + projectSortOrder, lastUpdated: new Date().toISOString() }; @@ -212,6 +217,56 @@ function ToolsSettings({ isOpen, onClose }) { + {/* Project Sorting */} +
+
+ +

+ Project Sorting +

+
+
+
+
+ Choose how projects are sorted in the sidebar +
+
+ + +
+
+ {projectSortOrder === 'name' + ? 'Projects are sorted alphabetically by name' + : 'Projects are sorted by most recent session activity'} +
+
+
+
+ {/* Allowed Tools */}