What's wrong
There are two defects in the per-row actions of ShowCompareBrowser (ProjectDirector/ProjectDirector.cs). They sit in the same handlers, so one PR can fix both.
1. Every row's buttons share one ImGui ID
- Directory rows (
:1946, :1950, :1968, :1972) and file rows (:2002, :2008, :2028, :2032) all use the literal labels ImGui.ArrowButton("##Copy", …) and ImGui.Button("X##Remove").
- The project never calls
ImGui.PushID, and ImGui tables do not push a per-row ID scope. So every Give/Take arrow has the same ID, and so does every X.
- With duplicate IDs, the first submitted item owns the active ID. On mouse release, that first button isn't hovered, so it clears the active ID and returns false. The button actually clicked on a later row never registers a press.
- Recent Dear ImGui builds also flag this as a conflicting ID.
2. The listing isn't refreshed after an action
BrowserContentsBase and BrowserContentsCompare are only rebuilt in SwitchCompareBrowserPath (:2227).
- None of the action handlers re-list the folder afterwards:
File.Copy / File.Delete at :2002-2034, and Directory.CreateDirectory / Directory.Delete at :1946-1974.
- So
existsInA != existsInB stays true and the Give/Take/X buttons stay on screen for a row that has already been acted on.
Failure scenario
At the top level of the compare browser, where #440's path-doubling doesn't apply: the base repo has .editorconfig and LICENSE.md, and the compare repo has neither.
- Click Give on the
LICENSE.md row. Nothing is copied; only the .editorconfig row's buttons respond. The same happens with X.
- Click Give on the
.editorconfig row. The file is copied, but the row still shows the Give arrow.
- Click it again.
File.Copy(src, dst) has no overwrite argument and throws IOException because the destination exists, inside the render callback.
- For a directory row, a second X makes
Directory.Delete throw DirectoryNotFoundException.
#440 covers the path doubling and the "catch IO errors" part. The duplicate IDs and the missing refresh are not covered there.
Suggested fix
- Wrap each row in
ImGui.PushID(path) / ImGui.PopID(), or make the labels unique, e.g. $"##Copy{path}" and $"X##Remove{path}".
- After a successful Give/Take/X, call
SwitchCompareBrowserPath(Options.BaseRepo, Options.CompareRepo, Options.BrowsePath), or update the two cached collections, so the row reflects the new state.
Acceptance criteria
- With two or more one-sided rows, Give/Take and X act on the row that was clicked.
- After an action, the row either disappears (it now exists on both sides, or on neither) or shows the correct remaining action. A second click can't raise an IO exception.
What's wrong
There are two defects in the per-row actions of
ShowCompareBrowser(ProjectDirector/ProjectDirector.cs). They sit in the same handlers, so one PR can fix both.1. Every row's buttons share one ImGui ID
:1946,:1950,:1968,:1972) and file rows (:2002,:2008,:2028,:2032) all use the literal labelsImGui.ArrowButton("##Copy", …)andImGui.Button("X##Remove").ImGui.PushID, and ImGui tables do not push a per-row ID scope. So every Give/Take arrow has the same ID, and so does every X.2. The listing isn't refreshed after an action
BrowserContentsBaseandBrowserContentsCompareare only rebuilt inSwitchCompareBrowserPath(:2227).File.Copy/File.Deleteat:2002-2034, andDirectory.CreateDirectory/Directory.Deleteat:1946-1974.existsInA != existsInBstays true and the Give/Take/X buttons stay on screen for a row that has already been acted on.Failure scenario
At the top level of the compare browser, where #440's path-doubling doesn't apply: the base repo has
.editorconfigandLICENSE.md, and the compare repo has neither.LICENSE.mdrow. Nothing is copied; only the.editorconfigrow's buttons respond. The same happens with X..editorconfigrow. The file is copied, but the row still shows the Give arrow.File.Copy(src, dst)has nooverwriteargument and throwsIOExceptionbecause the destination exists, inside the render callback.Directory.DeletethrowDirectoryNotFoundException.#440 covers the path doubling and the "catch IO errors" part. The duplicate IDs and the missing refresh are not covered there.
Suggested fix
ImGui.PushID(path)/ImGui.PopID(), or make the labels unique, e.g.$"##Copy{path}"and$"X##Remove{path}".SwitchCompareBrowserPath(Options.BaseRepo, Options.CompareRepo, Options.BrowsePath), or update the two cached collections, so the row reflects the new state.Acceptance criteria