Edit workspace files directly on web (#2270)

* feat(files): edit workspace files on web

Keep source buffers synchronized with host file changes and require an explicit overwrite or reload when revisions diverge.

* feat(panels): surface and protect modified tabs

Expose tooltip and modification state through the generic panel boundary so tabs can show stable metadata and guard every close route consistently.

* fix(tests): use portable fake timeout handle

* fix(files): harden editor conflict handling

Preserve modified panel state across tab eviction, use precise revisions for optimistic writes, coalesce concurrent file watchers, and localize the editor interface.

* fix(files): close editor concurrency gaps

Coalesce clean reloads, preserve subscriber identities and file permissions, suspend pending saves during close confirmation, and carry precise revisions through file reads.

* test(files): expect read revision metadata
This commit is contained in:
Mohamed Boudra
2026-07-21 04:41:19 +08:00
committed by GitHub
parent 9292f58896
commit 4bda2dfea9
69 changed files with 3678 additions and 241 deletions
+33
View File
@@ -470,6 +470,7 @@ export const ru: TranslationResources = {
},
tabs: {
loading: "Загрузка...",
modified: "Несохранённые изменения",
loadingAgentTitle: "Название агента загрузки",
emptyPane: "На этой панели нет вкладок.",
fallback: {
@@ -536,6 +537,13 @@ export const ru: TranslationResources = {
failedToReloadAgent: "Не удалось перезагрузить агент",
},
confirmations: {
unsavedTitle: "Несохранённые изменения",
unsavedMessage:
"В этой вкладке есть несохранённые изменения. При закрытии черновик будет удалён.",
closeWithoutSaving: "Закрыть без сохранения",
closePaneTitle: "Закрыть панель?",
bulkUnsaved:
"В {{count}} вкладках есть несохранённые изменения. При закрытии черновики будут удалены.",
close: "Закрывать",
cancel: "Отмена",
archive: "Архив",
@@ -1480,6 +1488,25 @@ export const ru: TranslationResources = {
binaryPreviewUnavailable: "Предварительный просмотр двоичного файла недоступен.",
failedToLoad: "Не удалось загрузить файл",
failedToLoadPreview: "Не удалось загрузить предварительный просмотр файла.",
editor: {
fileSize: "Размер файла {{size}}",
lines: "Строк: {{count}}",
editorStatus: "Состояние редактора: {{status}}",
unsavedChanges: "Несохранённые изменения",
saving: "Сохранение...",
saveFailed: "Не удалось сохранить",
changedOnDisk: "Изменён на диске",
vimMode: "Режим Vim {{mode}}",
cursor: "Строка {{line}}, столбец {{column}}",
preview: "Просмотр",
source: "Исходник",
unavailableTitle: "Файл недоступен на диске",
conflictDescription: "Локальный буфер сохранён. Выберите версию, которую нужно оставить.",
overwrite: "Перезаписать",
reload: "Перезагрузить",
reloadTitle: "Перезагрузить с диска?",
reloadMessage: "Локальные изменения будут потеряны.",
},
},
diff: {
changesLabel: "Изменения",
@@ -1575,12 +1602,18 @@ export const ru: TranslationResources = {
sections: {
general: "Общий",
appearance: "Появление",
editor: "Редактор",
shortcuts: "Ярлыки",
integrations: "Интеграции",
permissions: "Разрешения",
diagnostics: "Диагностика",
about: "О",
},
editor: {
title: "Редактор",
vimKeybindings: "Клавиши Vim",
vimHint: "Применяется к исходным файлам в веб- и настольной версии.",
},
hostSections: {
connections: "Соединения",
agents: "Agents",