Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: cancel update if view becomes out of focus #472

Merged

Conversation

8veStory
Copy link
Contributor

@8veStory 8veStory commented Mar 10, 2024

Fixes #462.

I work in a large monorepo and noticed that when :DiffviewOpen was used, and you switched to another tab, you would switch back to the Diffview window.

Reason for this being that inside the async function DiffView:update_file(), it is possible for the line local err, new_files = await(self:get_updated_files()) to take a long amount of time in large git repos. This meant it's possible for a user to switch to another tab prior to the async function completing, in which at the end of the function the user's window is switched to the DiffView.

I'm not entirely familiar with Lua but I made a very rough PR that changes the order of when re-rendering the panels work to abate this issue.

Copy link
Owner

@sindrets sindrets left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

The plugin probably needs a bigger refactor to better deal with synchronization issues. But in this case we should be able to improve the behavior considerably with a smaller change I think.

The problem isn't with rendering. Panels can render without changing focus. I think we should just cancel the file update if the view is no longer in focus when get_updated_files() settles. We can determine that by looking at the current tab page before and after awaiting this method. How about something like this:

diff --git a/lua/diffview/scene/views/diff/diff_view.lua b/lua/diffview/scene/views/diff/diff_view.lua
index 283fed9..84d9941 100644
--- a/lua/diffview/scene/views/diff/diff_view.lua
+++ b/lua/diffview/scene/views/diff/diff_view.lua
@@ -327,6 +327,12 @@ DiffView.update_files = debounce.debounce_trailing(
   async.wrap(function(self, callback)
     await(async.scheduler())
 
+    -- Never update unless the view is in focus
+    if self.tabpage ~= api.nvim_get_current_tabpage() then
+      callback({ "The update was cancelled." })
+      return
+    end
+
     ---@type PerfTimer
     local perf = PerfTimer("[DiffView] Status Update")
     self:ensure_layout()
@@ -344,19 +350,24 @@ DiffView.update_files = debounce.debounce_trailing(
     end
 
     local index_stat = pl:stat(pl:join(self.adapter.ctx.dir, "index"))
-    local last_winid = api.nvim_get_current_win()
 
     ---@type string[]?, FileDict
     local err, new_files = await(self:get_updated_files())
+    await(async.scheduler())
 
     if err then
       utils.err("Failed to update files in a diff view!", true)
       logger:error("[DiffView] Failed to update files!")
-      await(async.scheduler())
       callback(err)
       return
     end
 
+    -- Stop the update if the view is no longer in focus.
+    if self.tabpage ~= api.nvim_get_current_tabpage() then
+      callback({ "The update was cancelled." })
+      return
+    end
+
     perf:lap("received new file list")
 
     local files = {
@@ -365,8 +376,6 @@ DiffView.update_files = debounce.debounce_trailing(
       { cur_files = self.files.staged, new_files = new_files.staged },
     }
 
-    await(async.scheduler())
-
     for _, v in ipairs(files) do
       -- We diff the old file list against the new file list in order to find
       -- the most efficient way to morph the current list into the new. This
@@ -473,10 +482,6 @@ DiffView.update_files = debounce.debounce_trailing(
     end
     self:set_file(self.panel.cur_file or self.panel:next_file(), false, not self.initialized)
 
-    if api.nvim_win_is_valid(last_winid) then
-      api.nvim_set_current_win(last_winid)
-    end
-
     self.update_needed = false
     perf:time()
     logger:lvl(5):debug(perf)

@sindrets sindrets force-pushed the bug/window-switching-on-large-git-repo branch from d8c9d07 to b1fc589 Compare May 23, 2024 16:24
@sindrets sindrets changed the title bug: Involuntary Window Switching to DiffView when on Large Git Repo fix: cancel update if view becomes out of focus May 23, 2024
@sindrets sindrets merged commit 0bae1a3 into sindrets:main May 23, 2024
@sindrets
Copy link
Owner

@8veStory sorry for hijacking your PR. I think this should solve the issue you described, but let me know if you still have any problems, and we can iterate on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug] CTRL-W_T does not move focus to new tab
2 participants