diff --git a/lua/vgit/features/buffer/Hunks.lua b/lua/vgit/features/buffer/Hunks.lua index 0d02e721..1fb13d79 100644 --- a/lua/vgit/features/buffer/Hunks.lua +++ b/lua/vgit/features/buffer/Hunks.lua @@ -68,6 +68,9 @@ function Hunks:stage_all() local buffer = git_buffer_store.current() if not buffer then return end + -- Performance: Suppress VGitSync broadcast; refresh only this buffer after delay + git_buffer_store.suppress_sync_and_refresh(buffer, 200) + loop.free_textlock() local _, err = buffer:stage() if err then return console.debug.error(err) end @@ -82,6 +85,9 @@ function Hunks:cursor_stage() if not buffer then return end if buffer:editing() then return end + -- Performance: Suppress VGitSync broadcast; refresh only this buffer after delay + git_buffer_store.suppress_sync_and_refresh(buffer, 200) + if not buffer:is_tracked() then local _, err = buffer:stage() if err then return console.debug.error(err) end diff --git a/lua/vgit/features/screens/DiffScreen/init.lua b/lua/vgit/features/screens/DiffScreen/init.lua index 9cb78cb1..48fdd325 100644 --- a/lua/vgit/features/screens/DiffScreen/init.lua +++ b/lua/vgit/features/screens/DiffScreen/init.lua @@ -138,6 +138,10 @@ function DiffScreen:reset(buffer) local filename = self.model:get_filename() if not filename then return end + -- Performance: Suppress VGitSync broadcast; refresh only this buffer after delay + local git_buffer_store = require('vgit.git.git_buffer_store') + git_buffer_store.suppress_sync_and_refresh(buffer, 200) + loop.free_textlock() self.model:reset_file(filename) @@ -185,6 +189,10 @@ function DiffScreen:stage_hunk(buffer) local hunk, index = self.diff_view:get_hunk_under_cursor() if not hunk then return end + -- Performance: Suppress VGitSync broadcast; refresh only this buffer after delay + local git_buffer_store = require('vgit.git.git_buffer_store') + git_buffer_store.suppress_sync_and_refresh(buffer, 200) + self.model:stage_hunk(filename, hunk) loop.free_textlock() @@ -212,6 +220,10 @@ function DiffScreen:unstage_hunk(buffer) local hunk, index = self.diff_view:get_hunk_under_cursor() if not hunk then return end + -- Performance: Suppress VGitSync broadcast; refresh only this buffer after delay + local git_buffer_store = require('vgit.git.git_buffer_store') + git_buffer_store.suppress_sync_and_refresh(buffer, 200) + loop.free_textlock() self.model:unstage_hunk(filename, hunk) @@ -247,6 +259,10 @@ function DiffScreen:reset_hunk(buffer) if decision ~= 'yes' and decision ~= 'y' then return end + -- Performance: Suppress VGitSync broadcast; refresh only this buffer after delay + local git_buffer_store = require('vgit.git.git_buffer_store') + git_buffer_store.suppress_sync_and_refresh(buffer, 200) + loop.free_textlock() self.model:reset_hunk(filename, hunk) @@ -271,6 +287,10 @@ function DiffScreen:stage(buffer) local filename = self.model:get_filename() if not filename then return end + -- Performance: Suppress VGitSync broadcast; refresh only this buffer after delay + local git_buffer_store = require('vgit.git.git_buffer_store') + git_buffer_store.suppress_sync_and_refresh(buffer, 200) + loop.free_textlock() self.model:stage_file(filename) @@ -292,6 +312,10 @@ function DiffScreen:unstage(buffer) local filename = self.model:get_filename() if not filename then return end + -- Performance: Suppress VGitSync broadcast; refresh only this buffer after delay + local git_buffer_store = require('vgit.git.git_buffer_store') + git_buffer_store.suppress_sync_and_refresh(buffer, 200) + loop.free_textlock() self.model:unstage_file(filename) diff --git a/lua/vgit/git/git_buffer_store.lua b/lua/vgit/git/git_buffer_store.lua index 9af4c169..4f12cd0d 100644 --- a/lua/vgit/git/git_buffer_store.lua +++ b/lua/vgit/git/git_buffer_store.lua @@ -16,6 +16,9 @@ local events = { } local is_registered = false +-- When true, VGitSync events are suppressed (e.g., during staging operations) +local suppress_sync = false + local git_buffer_store = {} git_buffer_store.register_events = loop.coroutine(function() @@ -40,6 +43,8 @@ git_buffer_store.register_events = loop.coroutine(function() -- Use vim.schedule to avoid "must not be called in a lua loop callback" error vim.schedule(function() event.custom_on('VGitSync', function() + if suppress_sync then return end + git_buffer_store.for_each(function(buffer) git_buffer_store.dispatch(buffer, 'sync') end) @@ -181,4 +186,25 @@ git_buffer_store.collect = function() git_buffer_store.dispatch(git_buffer, 'attach') end +-- Suppress VGitSync broadcast and refresh only the specified buffer after delay. +-- This prevents refreshing all tracked buffers when only one needs updating. +-- +-- Note: External git operations during the suppression window won't trigger a +-- refresh until the next VGitSync event. This is an acceptable tradeoff given +-- the short window (typically 200ms). +git_buffer_store.suppress_sync_and_refresh = function(buffer, ms) + local git_buffer = git_buffer_store.get(buffer) + if not git_buffer then return end + + suppress_sync = true + + vim.defer_fn(loop.coroutine(function() + suppress_sync = false + + if git_buffer:is_valid() then + git_buffer_store.dispatch(git_buffer, 'sync') + end + end), ms) +end + return git_buffer_store