fix: resolve sidebar stale state after worktree, folder, project, and session mutations (#1038)
* fix: update sidebar store after worktree creation * fix: update sidebar store after worktree removal * fix: update sidebar store with correct key in removeProjectWorktree - Fixed key mismatch in sidebar store updates for worktree removal - Removed worktrees now properly disappear from sidebar - Aligned remove path with create path key resolution * fix: resolve sidebar stale state after folder, worktree, project, and session mutations * fix: now builds * Fix worktree sidebar store key --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
b62faadd15
commit
8fdc1e7e55
@@ -407,7 +407,7 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [currentDirectory, syncSessionStructureSignature]);
|
||||
}, [currentDirectory, syncSessionStructureSignature, projects]);
|
||||
|
||||
React.useEffect(() => {
|
||||
let refreshTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
@@ -922,7 +922,7 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
||||
normalizedSessionSearchQuery,
|
||||
filterSessionNodesForSearch,
|
||||
buildGroupSearchText,
|
||||
getFoldersForScope,
|
||||
foldersMap,
|
||||
});
|
||||
|
||||
const searchEmptyState = (
|
||||
@@ -1355,7 +1355,6 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
||||
expandedSessionGroups={expandedSessionGroups}
|
||||
collapsedGroups={collapsedGroups}
|
||||
hideDirectoryControls={hideDirectoryControls}
|
||||
getFoldersForScope={getFoldersForScope}
|
||||
collapsedFolderIds={collapsedFolderIds}
|
||||
toggleFolderCollapse={toggleFolderCollapse}
|
||||
renameFolder={renameFolder}
|
||||
@@ -1393,7 +1392,6 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
||||
expandedSessionGroups,
|
||||
collapsedGroups,
|
||||
hideDirectoryControls,
|
||||
getFoldersForScope,
|
||||
collapsedFolderIds,
|
||||
toggleFolderCollapse,
|
||||
renameFolder,
|
||||
|
||||
@@ -19,6 +19,7 @@ import type { SortableDragHandleProps } from './sortableItems';
|
||||
import type { GroupSearchData, SessionGroup, SessionNode } from './types';
|
||||
import { compareSessionsByPinnedAndTime, isBranchDifferentFromLabel, normalizePath, renderHighlightedText } from './utils';
|
||||
import type { SessionFolder } from '@/stores/useSessionFoldersStore';
|
||||
import { useSessionFoldersStore } from '@/stores/useSessionFoldersStore';
|
||||
import { useSessionDisplayStore } from '@/stores/useSessionDisplayStore';
|
||||
import { openExternalUrl } from '@/lib/url';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
@@ -42,7 +43,6 @@ type Props = {
|
||||
expandedSessionGroups: Set<string>;
|
||||
collapsedGroups: Set<string>;
|
||||
hideDirectoryControls: boolean;
|
||||
getFoldersForScope: (scopeKey: string) => SessionFolder[];
|
||||
collapsedFolderIds: Set<string>;
|
||||
toggleFolderCollapse: (folderId: string) => void;
|
||||
renameFolder: (scopeKey: string, folderId: string, name: string) => void;
|
||||
@@ -109,7 +109,6 @@ export function SessionGroupSection(props: Props): React.ReactNode {
|
||||
expandedSessionGroups,
|
||||
collapsedGroups,
|
||||
hideDirectoryControls,
|
||||
getFoldersForScope,
|
||||
collapsedFolderIds,
|
||||
toggleFolderCollapse,
|
||||
renameFolder,
|
||||
@@ -153,6 +152,7 @@ export function SessionGroupSection(props: Props): React.ReactNode {
|
||||
|
||||
const searchData = hasSessionSearchQuery ? groupSearchDataByGroup.get(group) : null;
|
||||
const displayMode = useSessionDisplayStore((state) => state.displayMode);
|
||||
const foldersMap = useSessionFoldersStore((state) => state.foldersMap);
|
||||
const isMinimalMode = displayMode === 'minimal';
|
||||
const isExpanded = expandedSessionGroups.has(groupKey);
|
||||
const isCollapsed = hasSessionSearchQuery ? false : collapsedGroups.has(groupKey);
|
||||
@@ -166,8 +166,8 @@ export function SessionGroupSection(props: Props): React.ReactNode {
|
||||
);
|
||||
const folderScopeKey = group.folderScopeKey ?? normalizePath(group.directory ?? null);
|
||||
const scopeFolders = React.useMemo(
|
||||
() => folderScopeKey ? getFoldersForScope(folderScopeKey) : [],
|
||||
[folderScopeKey, getFoldersForScope]
|
||||
() => folderScopeKey ? (foldersMap[folderScopeKey] ?? []) : [],
|
||||
[folderScopeKey, foldersMap]
|
||||
);
|
||||
|
||||
const nodeBySessionId = React.useMemo(() => {
|
||||
|
||||
@@ -208,6 +208,7 @@ const areEqual = (prev: Props, next: Props): boolean => {
|
||||
if ((prev.secondaryMeta?.branchLabel ?? null) !== (next.secondaryMeta?.branchLabel ?? null)) return false;
|
||||
if (prev.mobileVariant !== next.mobileVariant) return false;
|
||||
if ((prev.renderContext ?? 'project') !== (next.renderContext ?? 'project')) return false;
|
||||
if (prev.renamingFolderId !== next.renamingFolderId) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Session } from '@opencode-ai/sdk/v2';
|
||||
import type { SessionGroup, SessionNode, GroupSearchData } from '../types';
|
||||
import { dedupeSessionsById, normalizePath } from '../utils';
|
||||
import type { WorktreeMetadata } from '@/types/worktree';
|
||||
import type { SessionFoldersMap } from '@/stores/useSessionFoldersStore';
|
||||
|
||||
type ProjectItem = {
|
||||
id: string;
|
||||
@@ -39,7 +40,7 @@ type Args = {
|
||||
normalizedSessionSearchQuery: string;
|
||||
filterSessionNodesForSearch: (nodes: SessionNode[], query: string) => SessionNode[];
|
||||
buildGroupSearchText: (group: SessionGroup) => string;
|
||||
getFoldersForScope: (scopeKey: string) => Array<{ name: string }>;
|
||||
foldersMap: SessionFoldersMap;
|
||||
};
|
||||
|
||||
export const useSessionSidebarSections = (args: Args) => {
|
||||
@@ -56,7 +57,7 @@ export const useSessionSidebarSections = (args: Args) => {
|
||||
normalizedSessionSearchQuery,
|
||||
filterSessionNodesForSearch,
|
||||
buildGroupSearchText,
|
||||
getFoldersForScope,
|
||||
foldersMap,
|
||||
} = args;
|
||||
|
||||
const projectSections = React.useMemo<ProjectSection[]>(() => {
|
||||
@@ -107,9 +108,8 @@ export const useSessionSidebarSections = (args: Args) => {
|
||||
const matchedSessionCount = countNodes(filteredNodes);
|
||||
const groupMatches = buildGroupSearchText(group).includes(normalizedSessionSearchQuery);
|
||||
const scopeKey = normalizePath(group.directory ?? null);
|
||||
const folderNameMatchCount = scopeKey
|
||||
? getFoldersForScope(scopeKey).filter((folder) => folder.name.toLowerCase().includes(normalizedSessionSearchQuery)).length
|
||||
: 0;
|
||||
const scopeFolders = scopeKey ? (foldersMap[scopeKey] ?? []) : [];
|
||||
const folderNameMatchCount = scopeFolders.filter((folder) => folder.name.toLowerCase().includes(normalizedSessionSearchQuery)).length;
|
||||
|
||||
result.set(group, {
|
||||
filteredNodes,
|
||||
@@ -128,7 +128,7 @@ export const useSessionSidebarSections = (args: Args) => {
|
||||
filterSessionNodesForSearch,
|
||||
normalizedSessionSearchQuery,
|
||||
buildGroupSearchText,
|
||||
getFoldersForScope,
|
||||
foldersMap,
|
||||
]);
|
||||
|
||||
const searchableProjectSections = React.useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user