Skip to content

Compare browser: Give/Take and X only respond on the first row that shows them, and a row that was acted on stays listed until you navigate away #456

Description

@matt-edmondson

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.

  1. Click Give on the LICENSE.md row. Nothing is copied; only the .editorconfig row's buttons respond. The same happens with X.
  2. Click Give on the .editorconfig row. The file is copied, but the row still shows the Give arrow.
  3. Click it again. File.Copy(src, dst) has no overwrite argument and throws IOException because the destination exists, inside the render callback.
  4. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions