feat: add Files tab for browsing workspace files (#154)
* feat: add Files tab for browsing workspace files - Add Files tab between Diff and Terminal in header - Implement hierarchical file tree with expand/collapse - Add fuzzy search with debouncing and relevance ranking - Support gitignore filtering via `git check-ignore` (web + desktop) - Add syntax highlighting for 150+ file types - Add image preview (SVG, PNG, JPG, etc.) - Add line numbers, wrap toggle, and copy button - Desktop: split-pane layout matching DiffView - Mobile: drill-in navigation with full-width sidebar - Update help dialog with Cmd+3 shortcut - Increase header breakpoint to 940px for new tab * feat: enhance context and session stores to track agent/model/variant choices for historical sessions * feat: implement line selection and commenting functionality in FilesView
This commit is contained in:
committed by
GitHub
parent
ecf81c901d
commit
1be5dfda05
@@ -1,6 +1,11 @@
|
||||
|
||||
import { safeInvoke } from '../lib/tauriCallbackManager';
|
||||
import type { DirectoryListResult, FileSearchQuery, FileSearchResult, FilesAPI } from '@openchamber/ui/lib/api/types';
|
||||
import type { DirectoryListResult, FileSearchQuery, FileSearchResult, FilesAPI, ListDirectoryOptions } from '@openchamber/ui/lib/api/types';
|
||||
|
||||
type ReadFileBinaryResponse = {
|
||||
dataUrl: string;
|
||||
path: string;
|
||||
};
|
||||
|
||||
type ListDirectoryResponse = DirectoryListResult & {
|
||||
path?: string;
|
||||
@@ -39,11 +44,12 @@ const normalizeDirectoryPayload = (result: ListDirectoryResponse): DirectoryList
|
||||
});
|
||||
|
||||
export const createDesktopFilesAPI = (): FilesAPI => ({
|
||||
async listDirectory(path: string): Promise<DirectoryListResult> {
|
||||
async listDirectory(path: string, options?: ListDirectoryOptions): Promise<DirectoryListResult> {
|
||||
try {
|
||||
const result = await safeInvoke<ListDirectoryResponse>('list_directory', {
|
||||
path: normalizePath(path),
|
||||
includeHidden: false
|
||||
includeHidden: false,
|
||||
respectGitignore: options?.respectGitignore ?? false,
|
||||
}, {
|
||||
timeout: 10000,
|
||||
onCancel: () => {
|
||||
@@ -134,6 +140,28 @@ export const createDesktopFilesAPI = (): FilesAPI => ({
|
||||
}
|
||||
},
|
||||
|
||||
async readFileBinary(path: string): Promise<ReadFileBinaryResponse> {
|
||||
try {
|
||||
const normalizedPath = normalizePath(path);
|
||||
const result = await safeInvoke<ReadFileBinaryResponse>('read_file_binary', {
|
||||
path: normalizedPath
|
||||
}, {
|
||||
timeout: 15000,
|
||||
onCancel: () => {
|
||||
console.warn('[FilesAPI] Read binary file operation timed out');
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
dataUrl: result?.dataUrl ?? '',
|
||||
path: result?.path ? normalizePath(result.path) : normalizedPath,
|
||||
};
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
throw new Error(message || 'Failed to read file');
|
||||
}
|
||||
},
|
||||
|
||||
async writeFile(path: string, content: string): Promise<{ success: boolean; path: string }> {
|
||||
try {
|
||||
const normalizedPath = normalizePath(path);
|
||||
|
||||
Reference in New Issue
Block a user