Add mobile context notes tab (#1355)

* Add mobile context notes tab

* Fix bot comments

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
kostazol
2026-05-23 21:48:56 +03:00
committed by GitHub
co-authored by Konstantin Zolin Bohdan Triapitsyn
parent 0244d7ffcd
commit 9af0de0056
15 changed files with 38 additions and 21 deletions
+8 -2
View File
@@ -655,6 +655,7 @@ export const Header: React.FC<HeaderProps> = ({
const { t } = useI18n();
const setSessionSwitcherOpen = useUIStore((state) => state.setSessionSwitcherOpen);
const toggleSidebar = useUIStore((state) => state.toggleSidebar);
const setRightSidebarOpen = useUIStore((state) => state.setRightSidebarOpen);
const toggleBottomTerminal = useUIStore((state) => state.toggleBottomTerminal);
const toggleRightSidebar = useUIStore((state) => state.toggleRightSidebar);
const openContextOverview = useUIStore((state) => state.openContextOverview);
@@ -1506,6 +1507,7 @@ export const Header: React.FC<HeaderProps> = ({
{ id: 'diff', label: t('layout.mainTab.diff'), icon: 'diff' },
{ id: 'files', label: t('layout.mainTab.files'), icon: "folder-6" },
{ id: 'terminal', label: t('layout.mainTab.terminal'), icon: "terminal-box" },
{ id: 'context', label: t('layout.mainTab.context'), icon: "file-list-2" },
);
return base;
@@ -1520,7 +1522,7 @@ export const Header: React.FC<HeaderProps> = ({
}, [shortcutOverrides]);
useEffect(() => {
if (!isMobile && (activeMainTab === 'git' || activeMainTab === 'terminal' || activeMainTab === 'diff' || activeMainTab === 'files')) {
if (!isMobile && (activeMainTab === 'git' || activeMainTab === 'terminal' || activeMainTab === 'diff' || activeMainTab === 'files' || activeMainTab === 'context')) {
setActiveMainTab('chat');
}
}, [activeMainTab, isMobile, setActiveMainTab]);
@@ -1626,13 +1628,16 @@ export const Header: React.FC<HeaderProps> = ({
const num = parseInt(e.key, 10);
if (num >= 1 && num <= tabs.length) {
e.preventDefault();
if (isMobile) {
setRightSidebarOpen(false);
}
setActiveMainTab(tabs[num - 1].id);
}
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [tabs, setActiveMainTab]);
}, [isMobile, setActiveMainTab, setRightSidebarOpen, tabs]);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
@@ -1995,6 +2000,7 @@ export const Header: React.FC<HeaderProps> = ({
onClick={() => {
if (isMobile) {
blurActiveElement();
setRightSidebarOpen(false);
}
setActiveMainTab(tab.id);
}}
@@ -4,7 +4,7 @@ import { Header } from './Header';
import { BottomTerminalDock } from './BottomTerminalDock';
import { Sidebar, SIDEBAR_CONTENT_WIDTH } from './Sidebar';
import { RightSidebar, RIGHT_SIDEBAR_CONTENT_WIDTH } from './RightSidebar';
import { RightSidebarTabs } from './RightSidebarTabs';
import { ProjectContextPanel, RightSidebarTabs } from './RightSidebarTabs';
import { ContextPanel } from './ContextPanel';
import { ErrorBoundary } from '../ui/ErrorBoundary';
import { CommandPalette } from '../ui/CommandPalette';
@@ -308,6 +308,13 @@ export const MainLayout: React.FC = () => {
};
}, [isMobile, isTablet, setBottomTerminalOpen, setRightSidebarOpen]);
const handleToggleMobileRightDrawer = React.useCallback(() => {
if (mobileLeftDrawerOpen) {
setMobileLeftDrawerOpen(false);
}
setRightSidebarOpen(!isRightSidebarOpen);
}, [isRightSidebarOpen, mobileLeftDrawerOpen, setRightSidebarOpen]);
const secondaryView = React.useMemo(() => {
switch (activeMainTab) {
case 'plan':
@@ -320,6 +327,8 @@ export const MainLayout: React.FC = () => {
return <React.Suspense fallback={null}><TerminalView /></React.Suspense>;
case 'files':
return <React.Suspense fallback={null}><FilesView /></React.Suspense>;
case 'context':
return <React.Suspense fallback={null}><ProjectContextPanel /></React.Suspense>;
default:
return null;
}
@@ -361,12 +370,7 @@ export const MainLayout: React.FC = () => {
}
setMobileLeftDrawerOpen(!mobileLeftDrawerOpen);
},
toggleRightDrawer: () => {
if (mobileLeftDrawerOpen) {
setMobileLeftDrawerOpen(false);
}
setRightSidebarOpen(!isRightSidebarOpen);
},
toggleRightDrawer: handleToggleMobileRightDrawer,
leftDrawerX,
rightDrawerX,
leftDrawerWidth,
@@ -383,10 +387,7 @@ export const MainLayout: React.FC = () => {
setMobileLeftDrawerOpen(!mobileLeftDrawerOpen);
}}
onToggleRightDrawer={() => {
if (mobileLeftDrawerOpen) {
setMobileLeftDrawerOpen(false);
}
setRightSidebarOpen(!isRightSidebarOpen);
handleToggleMobileRightDrawer();
}}
leftDrawerOpen={mobileLeftDrawerOpen}
rightDrawerOpen={isRightSidebarOpen}
@@ -40,7 +40,7 @@ function useRightSidebarGitSync(directory: string | undefined, isSidebarOpen: bo
}, [directory, git, isSidebarOpen, ensureStatus]);
}
const ContextSidebarPanel: React.FC = () => {
export const ProjectContextPanel: React.FC = () => {
const activeProjectId = useProjectsStore((state) => state.activeProjectId);
const projects = useProjectsStore((state) => state.projects);
const homeDirectory = useDirectoryStore((state) => state.homeDirectory);
@@ -113,7 +113,7 @@ export const RightSidebarTabs: React.FC = () => {
{
id: 'context',
label: t('layout.rightSidebar.context'),
icon: <Icon name="booklet" className="h-3.5 w-3.5" />,
icon: <Icon name="file-list-2" className="h-3.5 w-3.5" />,
},
], [t]);
@@ -133,7 +133,7 @@ export const RightSidebarTabs: React.FC = () => {
<div className="min-h-0 flex-1 overflow-hidden">
{rightSidebarTab === 'git' && <GitView />}
{rightSidebarTab === 'files' && <SidebarFilesTree />}
{rightSidebarTab === 'context' && <ContextSidebarPanel />}
{rightSidebarTab === 'context' && <ProjectContextPanel />}
</div>
</div>
);
@@ -16,6 +16,7 @@ import type { SortableDragHandleProps } from './sortableItems';
import { SortableGroupItem, SortableProjectItem } from './sortableItems';
import { formatProjectLabel } from './utils';
import { useI18n } from '@/lib/i18n';
import type { MainTab } from '@/stores/useUIStore';
type ProjectSection = {
project: {
@@ -50,7 +51,7 @@ type Props = {
alwaysShowActions: boolean;
toggleProject: (id: string) => void;
setActiveProjectIdOnly: (id: string) => void;
setActiveMainTab: (tab: 'chat' | 'plan' | 'git' | 'diff' | 'terminal' | 'files') => void;
setActiveMainTab: (tab: MainTab) => void;
setSessionSwitcherOpen: (open: boolean) => void;
openNewSessionDraft: (options?: { directoryOverride?: string | null }) => void;
openNewWorktreeDialog: () => void;
@@ -2,6 +2,7 @@ import React from 'react';
import type { Session } from '@opencode-ai/sdk/v2';
import type { SessionGroup, SessionNode } from '../types';
import { normalizePath } from '../utils';
import type { MainTab } from '@/stores/useUIStore';
type ProjectSection = {
project: { id: string; normalizedPath: string };
@@ -18,7 +19,7 @@ type Args = {
newSessionDraftOpen: boolean;
mobileVariant: boolean;
openNewSessionDraft: (options?: { directoryOverride?: string | null }) => void;
setActiveMainTab: (tab: 'chat' | 'plan' | 'git' | 'diff' | 'terminal' | 'files') => void;
setActiveMainTab: (tab: MainTab) => void;
setSessionSwitcherOpen: (open: boolean) => void;
sessions: Session[];
worktreeMetadata: Map<string, { path?: string | null }>;
@@ -3,6 +3,7 @@ import type { Session } from '@opencode-ai/sdk/v2';
import { toast } from '@/components/ui';
import { copyTextToClipboard } from '@/lib/clipboard';
import { useI18n } from '@/lib/i18n';
import type { MainTab } from '@/stores/useUIStore';
type DeleteSessionConfirmSetter = React.Dispatch<React.SetStateAction<{
session: Session;
@@ -24,7 +25,7 @@ type Args = {
setIsSessionSearchOpen: (open: boolean) => void;
setActiveProjectIdOnly: (id: string) => void;
setDirectory: (directory: string, options?: { showOverlay?: boolean }) => void;
setActiveMainTab: (tab: 'chat' | 'plan' | 'git' | 'diff' | 'terminal' | 'files') => void;
setActiveMainTab: (tab: MainTab) => void;
setSessionSwitcherOpen: (open: boolean) => void;
setCurrentSession: (sessionId: string | null, directoryHint?: string | null) => void;
updateSessionTitle: (id: string, title: string) => Promise<void>;
+1
View File
@@ -24,6 +24,7 @@ export const dict = {
'layout.mainTab.diff': 'Diff',
'layout.mainTab.files': 'Files',
'layout.mainTab.terminal': 'Terminal',
'layout.mainTab.context': 'Context',
'layout.rightSidebar.git': 'Git',
'layout.rightSidebar.files': 'Files',
'layout.rightSidebar.context': 'Context',
+1
View File
@@ -25,6 +25,7 @@ export const dict: Record<I18nKey, string> = {
"layout.mainTab.diff": "Diff",
"layout.mainTab.files": "Archivos",
"layout.mainTab.terminal": "Terminal",
"layout.mainTab.context": "Contexto",
"layout.rightSidebar.git": "Git",
"layout.rightSidebar.files": "Archivos",
"layout.rightSidebar.context": "Contexto",
+1
View File
@@ -25,6 +25,7 @@ export const dict: Record<I18nKey, string> = {
'layout.mainTab.diff': '변경사항',
'layout.mainTab.files': '파일',
'layout.mainTab.terminal': '터미널',
'layout.mainTab.context': '컨텍스트',
'layout.rightSidebar.git': 'Git',
'layout.rightSidebar.files': '파일',
'layout.rightSidebar.context': '컨텍스트',
+1
View File
@@ -26,6 +26,7 @@ export const dict: Record<I18nKey, string> = {
'layout.mainTab.diff': 'Różnice',
'layout.mainTab.files': 'Pliki',
'layout.mainTab.terminal': 'Terminal',
'layout.mainTab.context': 'Kontekst',
'layout.rightSidebar.git': 'Git',
'layout.rightSidebar.files': 'Pliki',
'layout.rightSidebar.context': 'Kontekst',
@@ -25,6 +25,7 @@ export const dict: Record<I18nKey, string> = {
"layout.mainTab.diff": "Diff",
"layout.mainTab.files": "Arquivos",
"layout.mainTab.terminal": "Terminal",
"layout.mainTab.context": "Contexto",
"layout.rightSidebar.git": "Git",
"layout.rightSidebar.files": "Arquivos",
"layout.rightSidebar.context": "Contexto",
+1
View File
@@ -25,6 +25,7 @@ export const dict: Record<I18nKey, string> = {
"layout.mainTab.diff": "Diff",
"layout.mainTab.files": "Файли",
"layout.mainTab.terminal": "Термінал",
"layout.mainTab.context": "Контекст",
"layout.rightSidebar.git": "Git",
"layout.rightSidebar.files": "Файли",
"layout.rightSidebar.context": "Контекст",
@@ -25,6 +25,7 @@ export const dict: Record<I18nKey, string> = {
'layout.mainTab.diff': '差异',
'layout.mainTab.files': '文件',
'layout.mainTab.terminal': '终端',
'layout.mainTab.context': '上下文',
'layout.rightSidebar.git': 'Git',
'layout.rightSidebar.files': '文件',
'layout.rightSidebar.context': '上下文',
+1 -1
View File
@@ -7,7 +7,7 @@ import type { ShortcutCombo } from '@/lib/shortcuts';
import { DEFAULT_MONO_FONT, DEFAULT_UI_FONT, type MonoFontOption, type UiFontOption } from '@/lib/fontOptions';
import { getStoredMobileKeyboardMode, type MobileKeyboardMode } from '@/lib/mobileKeyboardMode';
export type MainTab = 'chat' | 'plan' | 'git' | 'diff' | 'terminal' | 'files';
export type MainTab = 'chat' | 'plan' | 'git' | 'diff' | 'terminal' | 'files' | 'context';
export type RightSidebarTab = 'git' | 'files' | 'context';
export type ContextPanelMode = 'diff' | 'file' | 'context' | 'plan' | 'chat' | 'preview' | 'browser';
export type MermaidRenderingMode = 'svg' | 'ascii';