Skip to content

Commit

Permalink
feat: refresh timeout on replace
Browse files Browse the repository at this point in the history
Closes #78
  • Loading branch information
rcarriga committed Apr 11, 2022
1 parent 0d02acf commit 486d6ad
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 38 deletions.
19 changes: 2 additions & 17 deletions lua/notify/init.lua
Expand Up @@ -40,9 +40,7 @@ function notify.setup(user_config)
local animator_stages = config.stages()
animator_stages = type(animator_stages) == "string" and stages[animator_stages] or animator_stages
local animator = WindowAnimator(animator_stages)
service = NotificationService(function(...)
return animator:render(...)
end)
service = NotificationService(animator)

vim.cmd([[command! Notifications :lua require("notify")._print_history()<CR>]])
end
Expand Down Expand Up @@ -128,20 +126,7 @@ function notify.notify(message, level, opts)
table.insert(notifications, notification)
local level_num = vim.lsp.log_levels[notification.level]
if opts.replace then
local notif_buf = service:replace(opts.replace, notification)
local win = vim.fn.bufwinid(notif_buf:buffer())
if win ~= -1 then
-- Highlights can change name if level changed so we have to re-link
-- vim.wo does not behave like setlocal, thus we use setwinvar to set a
-- local option. Otherwise our changes would affect subsequently opened
-- windows.
-- see e.g. neovim#14595
vim.fn.setwinvar(
win,
"&winhl",
"Normal:" .. notif_buf.highlights.body .. ",FloatBorder:" .. notif_buf.highlights.border
)
end
service:replace(opts.replace, notification)
elseif level_num >= config.level() then
service:push(notification)
end
Expand Down
26 changes: 19 additions & 7 deletions lua/notify/service/init.lua
Expand Up @@ -4,13 +4,13 @@ local NotificationBuf = require("notify.service.buffer")
---@class NotificationService
---@field private _running boolean
---@field private _pending FIFOQueue
---@field private _receiver fun(pending: FIFOQueue, time: number): boolean
---@field private _animator WindowAnimator
---@field private _buffers table<integer, NotificationBuf>
local NotificationService = {}

function NotificationService:new(receiver)
function NotificationService:new(animator)
local service = {
_receiver = receiver,
_animator = animator,
_pending = util.FIFOQueue(),
_running = false,
_buffers = {},
Expand All @@ -22,7 +22,7 @@ end

function NotificationService:_run()
self._running = true
local succees, updated = pcall(self._receiver, self._pending, 30 / 1000)
local succees, updated = pcall(self._animator.render, self._animator, self._pending, 30 / 1000)
if not succees then
print("Error running notification service: " .. updated)
self._running = false
Expand Down Expand Up @@ -51,7 +51,6 @@ function NotificationService:push(notif)
return buf
end

---@return NotificationBuf
function NotificationService:replace(id, notif)
local existing = self._buffers[id]
if not existing then
Expand All @@ -61,8 +60,21 @@ function NotificationService:replace(id, notif)
existing:set_notification(notif)
self._buffers[id] = nil
self._buffers[notif.id] = existing
existing:render()
return existing
pcall(existing.render, existing)
local win = vim.fn.bufwinid(existing:buffer())
if win ~= -1 then
-- Highlights can change name if level changed so we have to re-link
-- vim.wo does not behave like setlocal, thus we use setwinvar to set a
-- local option. Otherwise our changes would affect subsequently opened
-- windows.
-- see e.g. neovim#14595
vim.fn.setwinvar(
win,
"&winhl",
"Normal:" .. existing.highlights.body .. ",FloatBorder:" .. existing.highlights.border
)
self._animator:on_refresh(win)
end
end

function NotificationService:dismiss(opts)
Expand Down
43 changes: 30 additions & 13 deletions lua/notify/windows/init.lua
Expand Up @@ -9,7 +9,7 @@ local max = math.max
---@field win_states table<number, table<string, SpringState>>
---@field win_stages table<number, string>
---@field notif_bufs table<number, NotificationBuf>
---@field timed table
---@field timers table
---@field stages table
local WindowAnimator = {}

Expand All @@ -18,7 +18,7 @@ function WindowAnimator:new(stages)
win_stages = {},
win_states = {},
notif_bufs = {},
timed = {},
timers = {},
stages = stages,
}
self.__index = self
Expand Down Expand Up @@ -123,24 +123,41 @@ function WindowAnimator:remove_win(win)
notif_buf:close(win)
end

function WindowAnimator:on_refresh(win)
local notif_buf = self.notif_bufs[win]
if not notif_buf then
return
end
if self.timers[win] then
self.timers[win]:set_repeat(notif_buf:timeout() or config.default_timeout())
self.timers[win]:again()
end
end

function WindowAnimator:update_states(time, goals)
for win, win_goals in pairs(goals) do
if win_goals.time and not self.timed[win] then
if win_goals.time and not self.timers[win] then
local buf_time = self.notif_bufs[win]:timeout()
if buf_time ~= false then
if buf_time == true then
buf_time = nil
end
self.timed[win] = true
local timer_func = function()
self.timed[win] = nil
local notif_buf = self.notif_bufs[win]
if notif_buf and notif_buf:should_stay() then
return
end
self:advance_stage(win)
end
vim.defer_fn(timer_func, buf_time or config.default_timeout())
local timer = vim.loop.new_timer()
self.timers[win] = timer
local advance_time = buf_time or config.default_timeout()
timer:start(
advance_time,
advance_time,
vim.schedule_wrap(function()
timer:stop()
self.timers[win] = nil
local notif_buf = self.notif_bufs[win]
if notif_buf and notif_buf:should_stay() then
return
end
self:advance_stage(win)
end)
)
end
end

Expand Down
14 changes: 13 additions & 1 deletion tests/unit/init_spec.lua
Expand Up @@ -130,11 +130,23 @@ describe("checking public interface", function()
end)

a.it("doesn't render notification below config level", function()
local win = notify.async("test", "debug", { message = { string.rep("a", 16), "" } })
notify.async("test", "debug", { message = { string.rep("a", 16), "" } })
a.util.sleep(500)
local bufs = vim.api.nvim_list_bufs()
for _, buf in ipairs(bufs) do
assert.Not.same(vim.api.nvim_buf_get_option(buf, "filetype"), "notify")
end
end)
a.it("refreshes timeout on replace", function()
-- Don't want to spend time animating
notify.setup({ background_colour = "#000000", stages = "static" })

local notif = notify.async("test", "error", { timeout = 500 })
local win = notif.events.open()
a.util.sleep(300)
notify.async("test2", "error", { replace = notif })
a.util.sleep(300)
a.util.scheduler()
assert(vim.api.nvim_win_is_valid(win))
end)
end)

0 comments on commit 486d6ad

Please sign in to comment.