feat(merge): Rider-style 3-pane conflict editor view

Replace the Base|Ours|Theirs read-only columns + single-conflict result with a
whole-file 3-pane editor: Ours (read-only) | editable Result | Theirs (read-only),
reconstructed from the active file's segments so the panes line up on stable text.

- IBackgroundRenderer paints each conflict block (unresolved=blood, resolved=green)
  across all three panes.
- Result document edits are gated by an IReadOnlySectionProvider (stable text is
  read-only; only conflict regions, tracked via TextAnchors, are editable); edits
  flow back to the owning block.
- Between-pane gutters host inline accept controls (>/< ) positioned per conflict;
  click accepts ours/theirs into the result.
- Proportional synced vertical scroll across the panes; file switcher + change-nav
  arrows (F8 / Shift+F8); active-file 'M conflicts - K resolved' readout.
- Merge block tints + AmberBrush tokens; en/de keys for the new labels.

Seam unchanged. App builds; Ui.Tests 128, Localization.Tests 16.
This commit is contained in:
Mika Kuns
2026-06-19 10:15:12 +02:00
parent 378a92c156
commit c4d1acc75b
6 changed files with 432 additions and 97 deletions
+8 -7
View File
@@ -400,13 +400,14 @@
"windowTitle": "Merge-Konflikte lösen",
"modalTitle": "KONFLIKTE LÖSEN",
"loading": "Konflikte werden geladen…",
"current": "Aktuell (unsere)",
"incoming": "Eingehend (ihre)",
"mergedResult": "Zusammengeführtes Ergebnis",
"acceptCurrent": "Aktuelle übernehmen",
"acceptIncoming": "Eingehende übernehmen",
"acceptBoth": "Beide übernehmen",
"editManually": "Manuell bearbeiten",
"ours": "OURS · aktuell (Ziel-Branch)",
"result": "ERGEBNIS",
"theirs": "THEIRS · eingehend (Task)",
"binaryHint": "Binärdateien können hier nicht zusammengeführt werden — brich ab und löse sie in deinem Editor:",
"prevConflict": "Vorheriger Konflikt (Umschalt+F8)",
"nextConflict": "Nächster Konflikt (F8)",
"acceptOurs": "Ours ins Ergebnis übernehmen",
"acceptTheirs": "Theirs ins Ergebnis übernehmen",
"continue": "Lösen & fortfahren",
"abort": "Merge abbrechen"
},
+8 -7
View File
@@ -400,13 +400,14 @@
"windowTitle": "Resolve merge conflicts",
"modalTitle": "RESOLVE CONFLICTS",
"loading": "Loading conflicts…",
"current": "Current (ours)",
"incoming": "Incoming (theirs)",
"mergedResult": "Merged result",
"acceptCurrent": "Accept Current",
"acceptIncoming": "Accept Incoming",
"acceptBoth": "Accept Both",
"editManually": "Edit manually",
"ours": "OURS · current (merge target)",
"result": "RESULT",
"theirs": "THEIRS · incoming (task)",
"binaryHint": "Binary files can't be merged here — abort and resolve them in your editor:",
"prevConflict": "Previous conflict (Shift+F8)",
"nextConflict": "Next conflict (F8)",
"acceptOurs": "Accept ours into result",
"acceptTheirs": "Accept theirs into result",
"continue": "Resolve & continue",
"abort": "Abort merge"
},