- Introduced `EditorErrorBoundary` component to catch runtime errors in CodeMirror, providing a fallback UI to prevent crashes. - Updated file handling logic to utilize `isbinaryfile` for more reliable binary detection, replacing manual null-byte scans. - Enhanced `openFile` method to prevent duplicate tabs for already opened files. - Improved documentation for new components and updated file lists to reflect recent changes. - Optimized file watcher and path validation processes for better performance and reliability.
83 lines
5 KiB
Markdown
83 lines
5 KiB
Markdown
# Итерация 3: Multi-tab + создание/удаление файлов
|
||
|
||
> Зависит от: [Итерация 2](iter-2-editable-save.md)
|
||
|
||
## Цель
|
||
|
||
Поддержка нескольких открытых файлов во вкладках. Контекстное меню: создать файл/папку, удалить. Tab management.
|
||
|
||
## Новые npm-зависимости
|
||
|
||
`@radix-ui/react-context-menu` (`pnpm add @radix-ui/react-context-menu`) — для нативного контекстного меню. Проверить текущие `@radix-ui/*` версии в package.json и использовать совместимую.
|
||
|
||
## IPC каналы
|
||
|
||
| Канал | Описание |
|
||
|-------|----------|
|
||
| `editor:createFile` | Создать файл (validateFileName + валидация parentDir) |
|
||
| `editor:createDir` | Создать директорию |
|
||
| `editor:deleteFile` | Удалить файл через `shell.trashItem()` (безопасно) |
|
||
|
||
## Новые файлы
|
||
|
||
| # | Файл | Описание |
|
||
|---|------|----------|
|
||
| 1 | `src/renderer/components/team/editor/EditorContextMenu.tsx` | Context menu (New File, New Folder, Delete, Reveal in Finder) |
|
||
| 2 | `src/renderer/components/team/editor/NewFileDialog.tsx` | Inline-input для имени файла/папки |
|
||
| 3 | `src/renderer/utils/tabLabelDisambiguation.ts` | `getDisambiguatedTabLabel()` для дублей "index.ts" |
|
||
|
||
## Изменения в существующих файлах
|
||
|
||
| # | Файл | Изменение |
|
||
|---|------|-----------|
|
||
| 1 | `src/shared/types/editor.ts` | Типы для create/delete |
|
||
| 2 | `src/shared/types/api.ts` | `createFile`, `createDir`, `deleteFile` в EditorAPI |
|
||
| 3 | `src/main/services/editor/ProjectFileService.ts` | `createFile()`, `createDir()`, `deleteFile()` |
|
||
| 4 | `src/main/ipc/editor.ts` | 3 новых handler |
|
||
| 5 | `src/preload/index.ts` | 3 новых метода |
|
||
| 6 | `src/preload/constants/ipcChannels.ts` | `EDITOR_CREATE_FILE`, `EDITOR_CREATE_DIR`, `EDITOR_DELETE_FILE` |
|
||
| 7 | `src/renderer/components/team/editor/EditorTabBar.tsx` | Multi-tab: массив, переключение, close, middle-click close |
|
||
| 8 | `src/renderer/components/team/editor/EditorFileTree.tsx` | Right-click context menu, refresh после create/delete |
|
||
| 9 | `src/renderer/store/slices/editorSlice.ts` | Tab management actions, file operations |
|
||
|
||
## Security-требования
|
||
|
||
1. `createFile`: `validateFileName()` -- запрет `.`, `..`, control chars, path separators, NUL, length > 255. Валидировать и `parentDir`, и `path.join(parentDir, name)` (SEC-7)
|
||
2. `deleteFile`: `shell.trashItem()`, НЕ `fs.unlink()`. `validateFilePath()` обязательна
|
||
3. Confirmation dialog перед удалением
|
||
4. `createFile`, `createDir`, `deleteFile`: `isGitInternalPath()` блокирует операции внутри `.git/` (SEC-12, аналог writeFile из iter-2)
|
||
|
||
## Performance-требования
|
||
|
||
- Tab closing: `stateCache.delete(tabId)` (явная очистка памяти). closeAllTabs: `stateCache.clear()`
|
||
- Debounce обновления дерева после create/delete (500ms), не перечитывать после каждой операции
|
||
|
||
## UX-требования
|
||
|
||
- Disambiguation tab labels: два "index.ts" -> "(main/utils)" и "(renderer/utils)"
|
||
- Длинные имена: max-width ~160px, `truncate`, tooltip. Modified dot ПЕРЕД текстом
|
||
- ARIA для tab bar: `role="tablist"`, `role="tab"`, `aria-selected`, `role="tabpanel"`
|
||
|
||
## Тестирование
|
||
|
||
| # | Что тестировать | Файл |
|
||
|---|----------------|------|
|
||
| 1 | `ProjectFileService.createFile/deleteFile` с mock fs | `test/main/services/editor/ProjectFileService.test.ts` (расширение) |
|
||
| 2 | `editorSlice` -- multi-tab actions (open, close, reorder) | `test/renderer/store/editorSlice.test.ts` (расширение) |
|
||
| 3 | `tabLabelDisambiguation.ts` -- unit тесты | `test/renderer/utils/tabLabelDisambiguation.test.ts` |
|
||
| 4 | `EditorContextMenu` -- рендеринг, клики | `test/renderer/components/team/editor/EditorContextMenu.test.ts` |
|
||
| 5 | Manual: несколько файлов -> вкладки -> создать файл -> удалить файл | — |
|
||
|
||
## Критерии готовности
|
||
|
||
- [ ] Несколько файлов открыты одновременно
|
||
- [ ] Вкладки переключаются, закрываются (X, middle-click)
|
||
- [ ] Right-click -> New File, New Folder, Delete
|
||
- [ ] Создание файла добавляет в дерево + автоматически открывает
|
||
- [ ] Удаление через Trash с confirmation
|
||
- [ ] Disambiguation labels для дублирующихся имён
|
||
|
||
## Оценка
|
||
|
||
- **Надёжность решения: 7/10** -- file operations с правильной валидацией и trash -- надёжный подход.
|
||
- **Уверенность: 8/10** -- паттерны файловых операций отработаны.
|