file viewer: edit Markdown with optimistic-lock conflict detection
Nightly Build / build (push) Successful in 6m47s

- GET /api/file returns ETag (mtime+size) + X-Writable on disk files;
  PUT /api/file accepts optional if_match -> 409 Conflict on stale version
  (last-write-wins preserved when omitted), echoes the new ETag
- FileViewerBase: View | Edit tabs for .md when the caller can write;
  source textarea with Save/Cancel, live preview while editing
- Watcher no longer clobbers the buffer mid-edit: while editing with
  unsaved changes it probes the server ETag and only raises a conflict
  when the remote actually moved on (own-save echo is ignored)
- Conflict banner: Reload remote | Copy mine, then reload | Overwrite
- i18n (en/it/fr) + CSS; docs/projects.md updated
This commit is contained in:
2026-07-23 22:03:43 +01:00
parent 798e55951b
commit 3c52587dee
8 changed files with 446 additions and 9 deletions
+7
View File
@@ -238,6 +238,13 @@ impl ApiError {
pub fn payload_too_large(msg: impl Into<String>) -> Self {
Self { status: StatusCode::PAYLOAD_TOO_LARGE, message: msg.into() }
}
/// `409 Conflict` — used by the file editor's optimistic locking: the
/// caller sent an `if_match` ETag that no longer matches the file on disk
/// (someone else — another user, another tab, or an agent — wrote first).
pub fn conflict(msg: impl Into<String>) -> Self {
Self { status: StatusCode::CONFLICT, message: msg.into() }
}
}
/// Resolves the authenticated caller's per-user runtime context, or `401` when the