Files
headquarter/openspec/changes/archive/2026-05-19-file-editor/design.md
T
2026-05-19 16:05:30 +02:00

192 lines
4.8 KiB
Markdown

# File Editor - Design
## Architecture
```
RepoWorkspace
└── FileEditor (replaces FileViewer)
├── View Mode
│ ├── Toolbar (Edit button, file info)
│ ├── SyntaxHighlighter (Prism.js)
│ └── Line numbers
└── Edit Mode
├── Toolbar (Save, Cancel, file info)
├── Editor (react-simple-code-editor)
└── Line numbers
↓ [Save clicked]
CommitDialog
├── Diff preview
├── Commit message input
└── Author info
```
## Component Design
### FileEditor
**Props:**
```typescript
interface FileEditorProps {
projectId: string;
repoId: string;
filePath: string;
branch: string;
}
```
**State:**
```typescript
interface FileEditorState {
mode: 'view' | 'edit';
content: string;
originalContent: string;
language: string;
loading: boolean;
error: string | null;
showCommitDialog: boolean;
}
```
**Flow:**
1. Load file content on mount/file change
2. Detect language from file extension
3. Display in view mode by default
4. Click "Edit" → switch to edit mode
5. Make changes → click "Save"
6. Show commit dialog with diff
7. Enter commit message → commit
8. Return to view mode with updated content
### SyntaxHighlighter (View Mode)
**Implementation:**
- Use Prism.js for tokenization
- Render highlighted tokens as HTML
- Add line numbers via CSS counter
- Copy-to-clipboard button
**Language Detection:**
```typescript
const detectLanguage = (filename: string): string => {
const ext = filename.split('.').pop()?.toLowerCase();
const langMap: Record<string, string> = {
'js': 'javascript',
'ts': 'typescript',
'tsx': 'tsx',
'jsx': 'jsx',
'py': 'python',
'md': 'markdown',
// ... more mappings
};
return langMap[ext || ''] || 'plaintext';
};
```
### CodeEditor (Edit Mode)
**Implementation:**
- react-simple-code-editor component
- Prism.js highlighting via textarea overlay
- Line numbers synchronized with content
- Tab key support (inserts spaces)
**Features:**
- Syntax highlighting while typing
- Auto-indentation
- Line numbers
- Selection highlighting
### CommitDialog
**Props:**
```typescript
interface CommitDialogProps {
isOpen: boolean;
filePath: string;
originalContent: string;
newContent: string;
onCommit: (message: string) => void;
onCancel: () => void;
}
```
**Features:**
- Diff preview (simple line-by-line comparison)
- Commit message input (required)
- Author info (from user profile)
- Cancel button (returns to edit mode)
## API Integration
### Load File (existing)
```
GET /projects/{id}/repositories/{id}/files/content
Query: branch, path
```
### Save File (existing)
```
POST /projects/{id}/repositories/{id}/files/content
Body: {
path: string,
branch: string,
content: string,
commit_message: string,
author_name: string,
author_email: string
}
```
## Styling
### Editor Layout
```
┌─────────────────────────────────────────┐
│ [file.txt] [Edit] [Raw] │ ← Toolbar
├─────────────────────────────────────────┤
│ 1 │ function hello() { │ ← Line numbers + content
│ 2 │ return "world"; │
│ 3 │ } │
└─────────────────────────────────────────┘
```
### Colors
- Match existing app theme (CSS variables)
- Syntax colors:
- Keywords: var(--brand)
- Strings: #10b981
- Comments: var(--muted)
- Numbers: #f59e0b
- Functions: #3b82f6
### Responsive
- Editor takes full width on mobile
- Toolbar buttons shrink to icons
- Line numbers hidden on very small screens
## Implementation Order
1. **Install dependencies** - react-simple-code-editor, prismjs
2. **Create SyntaxHighlighter component** - Prism.js wrapper
3. **Create CodeEditor component** - Edit mode with highlighting
4. **Create CommitDialog component** - Commit flow
5. **Create FileEditor component** - Main component orchestrating modes
6. **Replace FileViewer in RepoWorkspace**
7. **Add CSS styles** - Editor styling, syntax colors
8. **Test** - Various file types, commit flow
## Error Handling
- **Binary files**: Show "Cannot edit binary files" message
- **Load errors**: Show retry button
- **Save errors**: Show error in commit dialog
- **Large files**: Show warning, offer to download instead
- **Network errors**: Show offline indicator
## Performance
- **Lazy load Prism** - Load language grammars on demand
- **Debounce edits** - Don't re-highlight on every keystroke
- **Virtual scrolling** - For files >1000 lines
- **Memoization** - Cache highlighted output