feat(ui): redesign workspace shell with context panel, tabbed sidebars, and faster diff UX (#433)
* feat: tabbed right sidebar, context panel, floating diff comments * fix: auto-close left sidebar when context panel opens - Increase default context panel width from 520 to 600 pixels - Increase sidebar minimum width from 200 to 300 pixels - Replace collapsible component with custom button in diff view * refactoring: rework sidebars, tabs, and file tree layout - Rewrite AnimatedTabs as segment-style with sliding indicator - Upgrade SidebarFilesTree to match FilesView features (context menus, git status, file icons, CRUD dialogs, fuzzy search ranking) - Restructure FilesView header: tabs row + actions row, remove breadcrumbs - Show relative path in context panel header, track active tab - Allow left sidebar to stay open alongside context panel - Hide diff/files tabs from header on desktop (mobile-only) - Move chevron after group name in session sidebar - Compact tab heights in right sidebar and git view - Size PreviewToggleButton to match other action buttons - Remove directory loading spinner from folder icons * feat: add project icon and color customization - Enable users to assign custom icons to projects - Allow users to choose accent colors for projects - Stabilize repo status UI during project switching * feat: add scroll fade indicators to editor tabs * style: reduce spacing and icon sizes in header * style: adjust tab component padding from uniform to vertical-horizontal * feat: Add session state indicators to project tabs * feat: Enhance session status handling and improve UI responsiveness * fix: preserve upstream tracking on branch rename * fix: improve initial remote selection for pull requests - Uses saved remote name from previous session when available - Selects remote based on tracking branch when possible - Falls back to origin or first available remote * perf(diff): faster highlight, stable stacked scroll - split/unified Pierre worker pools; prefer shiki-wasm - align diff CSS line-height; disable scroll anchoring; drop WebKit compositing hacks - harden stacked pin/align (cancel on user scroll/input); prevent overscroll - make overlay scrollbar MutationObserver optional; disable for diff container * feat: handle binary files in diff view * fix: adjust project tabs layout and drag regions * style: update drag overlay visual styling * feat: enable number keys to switch projects in the sidebar * fix: recognize octet-stream as text-based MIME type * feat: add keyboard navigation to context panel * feat: add session pinning to sidebar - Pin important sessions to keep them at the top - Pinned sessions persist across browser sessions * refactor: move context usage display from chat input to header
This commit is contained in:
committed by
GitHub
parent
12606b9e53
commit
47c943b487
@@ -25,7 +25,7 @@ interface DirectoryGitState {
|
||||
branches: GitBranch | null;
|
||||
log: GitLogResponse | null;
|
||||
identity: GitIdentitySummary | null;
|
||||
diffCache: Map<string, { original: string; modified: string; fetchedAt: number }>;
|
||||
diffCache: Map<string, { original: string; modified: string; fetchedAt: number; isBinary?: boolean }>;
|
||||
lastStatusFetch: number;
|
||||
lastStatusChange: number;
|
||||
lastLogFetch: number;
|
||||
@@ -55,8 +55,8 @@ interface GitStore {
|
||||
fetchIdentity: (directory: string, git: GitAPI) => Promise<void>;
|
||||
fetchAll: (directory: string, git: GitAPI, options?: { force?: boolean }) => Promise<void>;
|
||||
|
||||
getDiff: (directory: string, filePath: string) => { original: string; modified: string; fetchedAt: number } | null;
|
||||
setDiff: (directory: string, filePath: string, diff: { original: string; modified: string }) => void;
|
||||
getDiff: (directory: string, filePath: string) => { original: string; modified: string; fetchedAt: number; isBinary?: boolean } | null;
|
||||
setDiff: (directory: string, filePath: string, diff: { original: string; modified: string; isBinary?: boolean }) => void;
|
||||
clearDiffCache: (directory: string) => void;
|
||||
fetchAllDiffs: (directory: string, git: GitAPI) => Promise<void>;
|
||||
|
||||
@@ -72,6 +72,7 @@ interface GitFileDiffResponse {
|
||||
original: string;
|
||||
modified: string;
|
||||
path: string;
|
||||
isBinary?: boolean;
|
||||
}
|
||||
|
||||
interface GitAPI {
|
||||
@@ -98,10 +99,10 @@ const createEmptyDirectoryState = (): DirectoryGitState => ({
|
||||
|
||||
// LRU eviction helper for diff cache
|
||||
const evictDiffCacheIfNeeded = (
|
||||
diffCache: Map<string, { original: string; modified: string; fetchedAt: number }>,
|
||||
diffCache: Map<string, { original: string; modified: string; fetchedAt: number; isBinary?: boolean }>,
|
||||
maxEntries: number = DIFF_CACHE_MAX_ENTRIES,
|
||||
maxTotalSize: number = DIFF_CACHE_MAX_TOTAL_SIZE_BYTES
|
||||
): Map<string, { original: string; modified: string; fetchedAt: number }> => {
|
||||
): Map<string, { original: string; modified: string; fetchedAt: number; isBinary?: boolean }> => {
|
||||
// Calculate total size
|
||||
let totalSize = 0;
|
||||
for (const entry of diffCache.values()) {
|
||||
@@ -117,7 +118,7 @@ const evictDiffCacheIfNeeded = (
|
||||
const entries = Array.from(diffCache.entries())
|
||||
.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);
|
||||
|
||||
const newCache = new Map<string, { original: string; modified: string; fetchedAt: number }>();
|
||||
const newCache = new Map<string, { original: string; modified: string; fetchedAt: number; isBinary?: boolean }>();
|
||||
let newTotalSize = 0;
|
||||
|
||||
// Keep entries from newest to oldest until limits are reached
|
||||
@@ -441,6 +442,7 @@ export const useGitStore = create<GitStore>()(
|
||||
|
||||
// Pre-fetch all diffs so they're ready when user opens Diff tab
|
||||
void get().fetchAllDiffs(directory, git);
|
||||
|
||||
},
|
||||
|
||||
getDiff: (directory, filePath) => {
|
||||
@@ -481,7 +483,7 @@ export const useGitStore = create<GitStore>()(
|
||||
if (limitedFilesToFetch.length === 0) return;
|
||||
|
||||
let nextIndex = 0;
|
||||
const results: Array<{ path: string; diff: { original: string; modified: string } }> = [];
|
||||
const results: Array<{ path: string; diff: { original: string; modified: string; isBinary?: boolean } }> = [];
|
||||
|
||||
const takeNext = () => {
|
||||
const current = nextIndex;
|
||||
@@ -497,7 +499,7 @@ export const useGitStore = create<GitStore>()(
|
||||
const response = await Promise.race([fetchPromise, timeoutPromise]);
|
||||
return {
|
||||
path: filePath,
|
||||
diff: { original: response.original ?? '', modified: response.modified ?? '' },
|
||||
diff: { original: response.original ?? '', modified: response.modified ?? '', isBinary: response.isBinary },
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user