feat(sidebar): project notes/todos live in right sidebar context tab
Replace the header sticky-note popover/mobile overlay with a dedicated Context tab in the right sidebar. Context is cycled by the right-sidebar shortcut alongside git and files, and persisted across reloads.
This commit is contained in:
@@ -1,15 +1,19 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { RiFolder3Line, RiGitBranchLine } from '@remixicon/react';
|
import { RiBookletLine, RiFolder3Line, RiGitBranchLine } from '@remixicon/react';
|
||||||
|
|
||||||
import { SortableTabsStrip } from '@/components/ui/sortable-tabs-strip';
|
import { SortableTabsStrip } from '@/components/ui/sortable-tabs-strip';
|
||||||
|
import { ProjectNotesTodoPanel } from '@/components/session/ProjectNotesTodoPanel';
|
||||||
import { GitView } from '@/components/views';
|
import { GitView } from '@/components/views';
|
||||||
import { useUIStore } from '@/stores/useUIStore';
|
|
||||||
import { useGitStore } from '@/stores/useGitStore';
|
import { useGitStore } from '@/stores/useGitStore';
|
||||||
|
import { useProjectsStore } from '@/stores/useProjectsStore';
|
||||||
|
import { useDirectoryStore } from '@/stores/useDirectoryStore';
|
||||||
|
import { useUIStore } from '@/stores/useUIStore';
|
||||||
import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs';
|
import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs';
|
||||||
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
|
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
|
||||||
|
import { formatDirectoryName } from '@/lib/utils';
|
||||||
import { SidebarFilesTree } from './SidebarFilesTree';
|
import { SidebarFilesTree } from './SidebarFilesTree';
|
||||||
|
|
||||||
type RightTab = 'git' | 'files';
|
type RightTab = 'git' | 'files' | 'context';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps git status fresh while the right sidebar is open.
|
* Keeps git status fresh while the right sidebar is open.
|
||||||
@@ -35,6 +39,56 @@ function useRightSidebarGitSync(directory: string | undefined, isSidebarOpen: bo
|
|||||||
}, [directory, git, isSidebarOpen, ensureStatus]);
|
}, [directory, git, isSidebarOpen, ensureStatus]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ContextSidebarPanel: React.FC = () => {
|
||||||
|
const activeProjectId = useProjectsStore((state) => state.activeProjectId);
|
||||||
|
const projects = useProjectsStore((state) => state.projects);
|
||||||
|
const homeDirectory = useDirectoryStore((state) => state.homeDirectory);
|
||||||
|
const gitDirectories = useGitStore((state) => state.directories);
|
||||||
|
|
||||||
|
const activeProject = React.useMemo(() => {
|
||||||
|
if (activeProjectId) {
|
||||||
|
return projects.find((project) => project.id === activeProjectId) ?? projects[0] ?? null;
|
||||||
|
}
|
||||||
|
return projects[0] ?? null;
|
||||||
|
}, [activeProjectId, projects]);
|
||||||
|
|
||||||
|
const projectRef = React.useMemo(() => {
|
||||||
|
if (!activeProject) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: activeProject.id,
|
||||||
|
path: activeProject.path,
|
||||||
|
};
|
||||||
|
}, [activeProject]);
|
||||||
|
|
||||||
|
const projectLabel = React.useMemo(() => {
|
||||||
|
if (!activeProject) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return activeProject.label?.trim()
|
||||||
|
|| formatDirectoryName(activeProject.path, homeDirectory)
|
||||||
|
|| activeProject.path;
|
||||||
|
}, [activeProject, homeDirectory]);
|
||||||
|
|
||||||
|
const canCreateWorktree = React.useMemo(() => {
|
||||||
|
if (!activeProject) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return gitDirectories.get(activeProject.path)?.isGitRepo === true;
|
||||||
|
}, [activeProject, gitDirectories]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="h-full min-h-0 overflow-auto bg-sidebar">
|
||||||
|
<ProjectNotesTodoPanel
|
||||||
|
projectRef={projectRef}
|
||||||
|
projectLabel={projectLabel}
|
||||||
|
canCreateWorktree={canCreateWorktree}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const RightSidebarTabs: React.FC = () => {
|
export const RightSidebarTabs: React.FC = () => {
|
||||||
const rightSidebarTab = useUIStore((state) => state.rightSidebarTab);
|
const rightSidebarTab = useUIStore((state) => state.rightSidebarTab);
|
||||||
const setRightSidebarTab = useUIStore((state) => state.setRightSidebarTab);
|
const setRightSidebarTab = useUIStore((state) => state.setRightSidebarTab);
|
||||||
@@ -54,6 +108,11 @@ export const RightSidebarTabs: React.FC = () => {
|
|||||||
label: 'Files',
|
label: 'Files',
|
||||||
icon: <RiFolder3Line className="h-3.5 w-3.5" />,
|
icon: <RiFolder3Line className="h-3.5 w-3.5" />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'context',
|
||||||
|
label: 'Context',
|
||||||
|
icon: <RiBookletLine className="h-3.5 w-3.5" />,
|
||||||
|
},
|
||||||
], []);
|
], []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -72,6 +131,7 @@ export const RightSidebarTabs: React.FC = () => {
|
|||||||
<div className="min-h-0 flex-1 overflow-hidden">
|
<div className="min-h-0 flex-1 overflow-hidden">
|
||||||
{rightSidebarTab === 'git' && <GitView />}
|
{rightSidebarTab === 'git' && <GitView />}
|
||||||
{rightSidebarTab === 'files' && <SidebarFilesTree />}
|
{rightSidebarTab === 'files' && <SidebarFilesTree />}
|
||||||
|
{rightSidebarTab === 'context' && <ContextSidebarPanel />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { RiLayoutLeftLine } from '@remixicon/react';
|
|||||||
import { toast } from '@/components/ui';
|
import { toast } from '@/components/ui';
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { isDesktopLocalOriginActive, isDesktopShell, isTauriShell, startDesktopWindowDrag } from '@/lib/desktop';
|
import { isDesktopLocalOriginActive, isDesktopShell, isTauriShell, startDesktopWindowDrag } from '@/lib/desktop';
|
||||||
import { MobileOverlayPanel } from '@/components/ui/MobileOverlayPanel';
|
|
||||||
import { sessionEvents } from '@/lib/sessionEvents';
|
import { sessionEvents } from '@/lib/sessionEvents';
|
||||||
import { formatDirectoryName, cn } from '@/lib/utils';
|
import { formatDirectoryName, cn } from '@/lib/utils';
|
||||||
import { useSessionUIStore } from '@/sync/session-ui-store';
|
import { useSessionUIStore } from '@/sync/session-ui-store';
|
||||||
@@ -16,11 +15,9 @@ import { useProjectsStore } from '@/stores/useProjectsStore';
|
|||||||
import { useUIStore } from '@/stores/useUIStore';
|
import { useUIStore } from '@/stores/useUIStore';
|
||||||
import { getSafeStorage } from '@/stores/utils/safeStorage';
|
import { getSafeStorage } from '@/stores/utils/safeStorage';
|
||||||
import { useGitStore, useGitAllBranches, useGitRepoStatusMap } from '@/stores/useGitStore';
|
import { useGitStore, useGitAllBranches, useGitRepoStatusMap } from '@/stores/useGitStore';
|
||||||
import { useDeviceInfo } from '@/lib/device';
|
|
||||||
import { isVSCodeRuntime } from '@/lib/desktop';
|
import { isVSCodeRuntime } from '@/lib/desktop';
|
||||||
import { NewWorktreeDialog } from './NewWorktreeDialog';
|
import { NewWorktreeDialog } from './NewWorktreeDialog';
|
||||||
import { ScheduledTasksDialog } from './ScheduledTasksDialog';
|
import { ScheduledTasksDialog } from './ScheduledTasksDialog';
|
||||||
import { ProjectNotesTodoPanel } from './ProjectNotesTodoPanel';
|
|
||||||
import { useSessionFoldersStore } from '@/stores/useSessionFoldersStore';
|
import { useSessionFoldersStore } from '@/stores/useSessionFoldersStore';
|
||||||
import { useDebouncedValue } from '@/hooks/useDebouncedValue';
|
import { useDebouncedValue } from '@/hooks/useDebouncedValue';
|
||||||
import { useArchivedAutoFolders } from './sidebar/hooks/useArchivedAutoFolders';
|
import { useArchivedAutoFolders } from './sidebar/hooks/useArchivedAutoFolders';
|
||||||
@@ -142,7 +139,6 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
|||||||
const [expandedSessionGroups, setExpandedSessionGroups] = React.useState<Set<string>>(new Set());
|
const [expandedSessionGroups, setExpandedSessionGroups] = React.useState<Set<string>>(new Set());
|
||||||
const [newWorktreeDialogOpen, setNewWorktreeDialogOpen] = React.useState(false);
|
const [newWorktreeDialogOpen, setNewWorktreeDialogOpen] = React.useState(false);
|
||||||
const [updateDialogOpen, setUpdateDialogOpen] = React.useState(false);
|
const [updateDialogOpen, setUpdateDialogOpen] = React.useState(false);
|
||||||
const [projectNotesPanelOpen, setProjectNotesPanelOpen] = React.useState(false);
|
|
||||||
const [openSidebarMenuKey, setOpenSidebarMenuKey] = React.useState<string | null>(null);
|
const [openSidebarMenuKey, setOpenSidebarMenuKey] = React.useState<string | null>(null);
|
||||||
const [renamingFolderId, setRenamingFolderId] = React.useState<string | null>(null);
|
const [renamingFolderId, setRenamingFolderId] = React.useState<string | null>(null);
|
||||||
const [renameFolderDraft, setRenameFolderDraft] = React.useState('');
|
const [renameFolderDraft, setRenameFolderDraft] = React.useState('');
|
||||||
@@ -230,7 +226,6 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
|||||||
const setSettingsDialogOpen = useUIStore((state) => state.setSettingsDialogOpen);
|
const setSettingsDialogOpen = useUIStore((state) => state.setSettingsDialogOpen);
|
||||||
const toggleHelpDialog = useUIStore((state) => state.toggleHelpDialog);
|
const toggleHelpDialog = useUIStore((state) => state.toggleHelpDialog);
|
||||||
const setAboutDialogOpen = useUIStore((state) => state.setAboutDialogOpen);
|
const setAboutDialogOpen = useUIStore((state) => state.setAboutDialogOpen);
|
||||||
const deviceInfo = useDeviceInfo();
|
|
||||||
const setSessionSwitcherOpen = useUIStore((state) => state.setSessionSwitcherOpen);
|
const setSessionSwitcherOpen = useUIStore((state) => state.setSessionSwitcherOpen);
|
||||||
const setScheduledTasksDialogOpen = useUIStore((state) => state.setScheduledTasksDialogOpen);
|
const setScheduledTasksDialogOpen = useUIStore((state) => state.setScheduledTasksDialogOpen);
|
||||||
const toggleSidebar = useUIStore((state) => state.toggleSidebar);
|
const toggleSidebar = useUIStore((state) => state.toggleSidebar);
|
||||||
@@ -893,44 +888,7 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const activeProjectForHeader = React.useMemo(
|
|
||||||
() => normalizedProjects.find((project) => project.id === activeProjectId) ?? normalizedProjects[0] ?? null,
|
|
||||||
[normalizedProjects, activeProjectId],
|
|
||||||
);
|
|
||||||
const activeProjectRefForHeader = React.useMemo(
|
|
||||||
() => (activeProjectForHeader
|
|
||||||
? {
|
|
||||||
id: activeProjectForHeader.id,
|
|
||||||
path: activeProjectForHeader.normalizedPath,
|
|
||||||
}
|
|
||||||
: null),
|
|
||||||
[activeProjectForHeader],
|
|
||||||
);
|
|
||||||
const activeProjectLabelForHeader = React.useMemo(
|
|
||||||
() => (activeProjectForHeader
|
|
||||||
? activeProjectForHeader.label?.trim()
|
|
||||||
|| formatDirectoryName(activeProjectForHeader.normalizedPath, homeDirectory)
|
|
||||||
|| activeProjectForHeader.normalizedPath
|
|
||||||
: null),
|
|
||||||
[activeProjectForHeader, homeDirectory],
|
|
||||||
);
|
|
||||||
|
|
||||||
const activeProjectIsRepo = React.useMemo(
|
|
||||||
() => (activeProjectForHeader ? Boolean(projectRepoStatus.get(activeProjectForHeader.id)) : false),
|
|
||||||
[activeProjectForHeader, projectRepoStatus],
|
|
||||||
);
|
|
||||||
// Only flip to false once the new project's status is actually resolved (present in map)
|
|
||||||
const stableActiveProjectIsRepo = activeProjectForHeader && projectRepoStatus.has(activeProjectForHeader.id)
|
|
||||||
? activeProjectIsRepo
|
|
||||||
: lastRepoStatusRef.current;
|
|
||||||
const reserveHeaderActionsSpace = true;
|
const reserveHeaderActionsSpace = true;
|
||||||
const useMobileNotesPanel = mobileVariant || deviceInfo.isMobile;
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!activeProjectForHeader) {
|
|
||||||
setProjectNotesPanelOpen(false);
|
|
||||||
}
|
|
||||||
}, [activeProjectForHeader]);
|
|
||||||
|
|
||||||
const { currentSessionDirectory } = useProjectSessionSelection({
|
const { currentSessionDirectory } = useProjectSessionSelection({
|
||||||
projectSections,
|
projectSections,
|
||||||
@@ -1479,14 +1437,8 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
|||||||
hideDirectoryControls={hideDirectoryControls}
|
hideDirectoryControls={hideDirectoryControls}
|
||||||
handleOpenDirectoryDialog={handleOpenDirectoryDialog}
|
handleOpenDirectoryDialog={handleOpenDirectoryDialog}
|
||||||
handleNewSession={handleSidebarNewSession}
|
handleNewSession={handleSidebarNewSession}
|
||||||
useMobileNotesPanel={useMobileNotesPanel}
|
|
||||||
projectNotesPanelOpen={projectNotesPanelOpen}
|
|
||||||
setProjectNotesPanelOpen={setProjectNotesPanelOpen}
|
|
||||||
activeProjectRefForHeader={activeProjectRefForHeader}
|
|
||||||
activeProjectLabelForHeader={activeProjectLabelForHeader}
|
|
||||||
canOpenMultiRun={projects.length > 0}
|
canOpenMultiRun={projects.length > 0}
|
||||||
openMultiRunLauncher={handleOpenMultiRunFromHeader}
|
openMultiRunLauncher={handleOpenMultiRunFromHeader}
|
||||||
stableActiveProjectIsRepo={stableActiveProjectIsRepo}
|
|
||||||
headerActionIconClass={headerActionIconClass}
|
headerActionIconClass={headerActionIconClass}
|
||||||
reserveHeaderActionsSpace={reserveHeaderActionsSpace}
|
reserveHeaderActionsSpace={reserveHeaderActionsSpace}
|
||||||
headerActionButtonClass={headerActionButtonClass}
|
headerActionButtonClass={headerActionButtonClass}
|
||||||
@@ -1594,22 +1546,6 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
|||||||
|
|
||||||
<ScheduledTasksDialog />
|
<ScheduledTasksDialog />
|
||||||
|
|
||||||
{useMobileNotesPanel ? (
|
|
||||||
<MobileOverlayPanel
|
|
||||||
open={projectNotesPanelOpen}
|
|
||||||
onClose={() => setProjectNotesPanelOpen(false)}
|
|
||||||
title={activeProjectLabelForHeader ? `Project notes - ${activeProjectLabelForHeader}` : 'Project notes'}
|
|
||||||
>
|
|
||||||
<ProjectNotesTodoPanel
|
|
||||||
projectRef={activeProjectRefForHeader}
|
|
||||||
projectLabel={activeProjectLabelForHeader}
|
|
||||||
canCreateWorktree={stableActiveProjectIsRepo}
|
|
||||||
onActionComplete={() => setProjectNotesPanelOpen(false)}
|
|
||||||
className="p-0"
|
|
||||||
/>
|
|
||||||
</MobileOverlayPanel>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<SessionDeleteConfirmDialog
|
<SessionDeleteConfirmDialog
|
||||||
value={deleteSessionConfirm}
|
value={deleteSessionConfirm}
|
||||||
setValue={setDeleteSessionConfirm}
|
setValue={setDeleteSessionConfirm}
|
||||||
|
|||||||
@@ -16,26 +16,17 @@ import {
|
|||||||
RiCloseLine,
|
RiCloseLine,
|
||||||
RiContractUpDownLine,
|
RiContractUpDownLine,
|
||||||
RiExpandUpDownLine,
|
RiExpandUpDownLine,
|
||||||
RiStickyNoteLine,
|
|
||||||
RiCalendarScheduleLine,
|
RiCalendarScheduleLine,
|
||||||
} from '@remixicon/react';
|
} from '@remixicon/react';
|
||||||
import { ArrowsMerge } from '@/components/icons/ArrowsMerge';
|
import { ArrowsMerge } from '@/components/icons/ArrowsMerge';
|
||||||
import type { ProjectRef } from '@/lib/openchamberConfig';
|
|
||||||
import { useSessionDisplayStore } from '@/stores/useSessionDisplayStore';
|
import { useSessionDisplayStore } from '@/stores/useSessionDisplayStore';
|
||||||
import { ProjectNotesTodoPanel } from '../ProjectNotesTodoPanel';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
hideDirectoryControls: boolean;
|
hideDirectoryControls: boolean;
|
||||||
handleOpenDirectoryDialog: () => void;
|
handleOpenDirectoryDialog: () => void;
|
||||||
handleNewSession: () => void;
|
handleNewSession: () => void;
|
||||||
useMobileNotesPanel: boolean;
|
|
||||||
projectNotesPanelOpen: boolean;
|
|
||||||
setProjectNotesPanelOpen: (open: boolean) => void;
|
|
||||||
activeProjectRefForHeader: ProjectRef | null;
|
|
||||||
activeProjectLabelForHeader: string | null;
|
|
||||||
canOpenMultiRun: boolean;
|
canOpenMultiRun: boolean;
|
||||||
openMultiRunLauncher: () => void;
|
openMultiRunLauncher: () => void;
|
||||||
stableActiveProjectIsRepo: boolean;
|
|
||||||
headerActionIconClass: string;
|
headerActionIconClass: string;
|
||||||
reserveHeaderActionsSpace: boolean;
|
reserveHeaderActionsSpace: boolean;
|
||||||
headerActionButtonClass: string;
|
headerActionButtonClass: string;
|
||||||
@@ -56,14 +47,8 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
hideDirectoryControls,
|
hideDirectoryControls,
|
||||||
handleOpenDirectoryDialog,
|
handleOpenDirectoryDialog,
|
||||||
handleNewSession,
|
handleNewSession,
|
||||||
useMobileNotesPanel,
|
|
||||||
projectNotesPanelOpen,
|
|
||||||
setProjectNotesPanelOpen,
|
|
||||||
activeProjectRefForHeader,
|
|
||||||
activeProjectLabelForHeader,
|
|
||||||
canOpenMultiRun,
|
canOpenMultiRun,
|
||||||
openMultiRunLauncher,
|
openMultiRunLauncher,
|
||||||
stableActiveProjectIsRepo,
|
|
||||||
headerActionIconClass,
|
headerActionIconClass,
|
||||||
reserveHeaderActionsSpace,
|
reserveHeaderActionsSpace,
|
||||||
headerActionButtonClass,
|
headerActionButtonClass,
|
||||||
@@ -150,49 +135,6 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
<TooltipContent side="bottom" sideOffset={4}><p>Scheduled tasks</p></TooltipContent>
|
<TooltipContent side="bottom" sideOffset={4}><p>Scheduled tasks</p></TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
{useMobileNotesPanel ? (
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => setProjectNotesPanelOpen(true)}
|
|
||||||
className={headerActionButtonClass}
|
|
||||||
aria-label="Project notes"
|
|
||||||
disabled={!activeProjectRefForHeader}
|
|
||||||
>
|
|
||||||
<RiStickyNoteLine className={headerActionIconClass} />
|
|
||||||
</button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent side="bottom" sideOffset={4}><p>Project notes</p></TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
) : (
|
|
||||||
<DropdownMenu open={projectNotesPanelOpen} onOpenChange={setProjectNotesPanelOpen} modal={false}>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={headerActionButtonClass}
|
|
||||||
aria-label="Project notes"
|
|
||||||
disabled={!activeProjectRefForHeader}
|
|
||||||
>
|
|
||||||
<RiStickyNoteLine className={headerActionIconClass} />
|
|
||||||
</button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent side="bottom" sideOffset={4}><p>Project notes</p></TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
<DropdownMenuContent align="start" className="w-[420px] max-w-[min(92vw,420px)] p-0">
|
|
||||||
<ProjectNotesTodoPanel
|
|
||||||
projectRef={activeProjectRefForHeader}
|
|
||||||
projectLabel={activeProjectLabelForHeader}
|
|
||||||
canCreateWorktree={stableActiveProjectIsRepo}
|
|
||||||
onActionComplete={() => setProjectNotesPanelOpen(false)}
|
|
||||||
/>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ export const useKeyboardShortcuts = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabs = ['git', 'files'] as const;
|
const tabs = ['git', 'files', 'context'] as const;
|
||||||
const currentIndex = tabs.indexOf(rightSidebarTab);
|
const currentIndex = tabs.indexOf(rightSidebarTab);
|
||||||
const nextTab = tabs[(currentIndex + 1) % tabs.length];
|
const nextTab = tabs[(currentIndex + 1) % tabs.length];
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { SEMANTIC_TYPOGRAPHY, getTypographyVariable, type SemanticTypographyKey
|
|||||||
import type { ShortcutCombo } from '@/lib/shortcuts';
|
import type { ShortcutCombo } from '@/lib/shortcuts';
|
||||||
|
|
||||||
export type MainTab = 'chat' | 'plan' | 'git' | 'diff' | 'terminal' | 'files';
|
export type MainTab = 'chat' | 'plan' | 'git' | 'diff' | 'terminal' | 'files';
|
||||||
export type RightSidebarTab = 'git' | 'files';
|
export type RightSidebarTab = 'git' | 'files' | 'context';
|
||||||
export type ContextPanelMode = 'diff' | 'file' | 'context' | 'plan' | 'chat';
|
export type ContextPanelMode = 'diff' | 'file' | 'context' | 'plan' | 'chat';
|
||||||
export type MermaidRenderingMode = 'svg' | 'ascii';
|
export type MermaidRenderingMode = 'svg' | 'ascii';
|
||||||
export type UserMessageRenderingMode = 'markdown' | 'plain';
|
export type UserMessageRenderingMode = 'markdown' | 'plain';
|
||||||
@@ -1828,7 +1828,10 @@ export const useUIStore = create<UIStore>()(
|
|||||||
delete state.memoryLimitActiveSession;
|
delete state.memoryLimitActiveSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof state.rightSidebarTab !== 'string' || (state.rightSidebarTab !== 'git' && state.rightSidebarTab !== 'files')) {
|
if (
|
||||||
|
typeof state.rightSidebarTab !== 'string'
|
||||||
|
|| (state.rightSidebarTab !== 'git' && state.rightSidebarTab !== 'files' && state.rightSidebarTab !== 'context')
|
||||||
|
) {
|
||||||
state.rightSidebarTab = 'git';
|
state.rightSidebarTab = 'git';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user