feat: Implement comprehensive notification system and fix overlapping issues
- Create custom notification manager to handle overlapping notifications - Fix notification positioning to avoid dashboard overlap - Improve alpha dashboard appearance and message suppression - Add smart notification routing for different contexts - Implement notification stacking and positioning logic - Add notification management keymaps for better control - Enhance startup message handling to prevent overlapping - Improve UI layout and reduce visual clutter - Add context-aware notifications (dashboard vs regular mode) - Implement notification clearing and testing functionality New features: - <leader>nc - Clear all notifications - <leader>nn - Test notification system - Smart notification positioning - Context-aware notification display - Notification stacking and management UI improvements: - Better dashboard appearance - Reduced overlapping elements - Cleaner startup experience - Improved notification aesthetics - Better message routing
This commit is contained in:
231
lua/cargdev/core/function/notification_manager.lua
Normal file
231
lua/cargdev/core/function/notification_manager.lua
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
-- Custom notification manager to handle overlapping and improve UX
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
-- Track active notifications to prevent overlapping
|
||||||
|
local active_notifications = {}
|
||||||
|
local notification_queue = {}
|
||||||
|
|
||||||
|
-- Function to show a notification without overlapping
|
||||||
|
function M.show_notification(message, level, opts)
|
||||||
|
level = level or vim.log.levels.INFO
|
||||||
|
opts = opts or {}
|
||||||
|
|
||||||
|
-- Default options
|
||||||
|
local default_opts = {
|
||||||
|
timeout = 3000,
|
||||||
|
title = "CarGDev Neovim",
|
||||||
|
render = "minimal",
|
||||||
|
stages = "fade_in_slide_out",
|
||||||
|
position = "top_right",
|
||||||
|
max_width = 50,
|
||||||
|
max_height = 8,
|
||||||
|
background_colour = "#000000",
|
||||||
|
border_style = "rounded",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Merge options
|
||||||
|
for k, v in pairs(default_opts) do
|
||||||
|
if opts[k] == nil then
|
||||||
|
opts[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if we're in alpha dashboard
|
||||||
|
local current_buf = vim.api.nvim_get_current_buf()
|
||||||
|
local current_ft = vim.api.nvim_buf_get_option(current_buf, "filetype")
|
||||||
|
|
||||||
|
if current_ft == "alpha" then
|
||||||
|
-- If in dashboard, use a different approach
|
||||||
|
M.show_dashboard_notification(message, level, opts)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Use nvim-notify if available
|
||||||
|
local notify_available = pcall(require, "notify")
|
||||||
|
if notify_available then
|
||||||
|
local notify = require("notify")
|
||||||
|
|
||||||
|
-- Position notification to avoid overlapping
|
||||||
|
opts.on_open = function(win)
|
||||||
|
-- Calculate position to avoid overlapping with other notifications
|
||||||
|
local row = 2
|
||||||
|
local col = vim.o.columns - 60
|
||||||
|
|
||||||
|
-- Adjust position if there are other notifications
|
||||||
|
for _, notif in ipairs(active_notifications) do
|
||||||
|
if notif.win and vim.api.nvim_win_is_valid(notif.win) then
|
||||||
|
row = row + 10 -- Stack notifications vertically
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Ensure notification doesn't go off-screen
|
||||||
|
if row > vim.o.lines - 15 then
|
||||||
|
row = 2
|
||||||
|
col = col - 20
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_win_set_config(win, {
|
||||||
|
row = row,
|
||||||
|
col = col,
|
||||||
|
relative = "editor",
|
||||||
|
width = opts.max_width,
|
||||||
|
height = opts.max_height,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Track this notification
|
||||||
|
table.insert(active_notifications, {
|
||||||
|
win = win,
|
||||||
|
message = message,
|
||||||
|
timestamp = vim.loop.now(),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on_close = function(win)
|
||||||
|
-- Remove from active notifications
|
||||||
|
for i, notif in ipairs(active_notifications) do
|
||||||
|
if notif.win == win then
|
||||||
|
table.remove(active_notifications, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show notification
|
||||||
|
local notification_id = notify(message, level, opts)
|
||||||
|
return notification_id
|
||||||
|
else
|
||||||
|
-- Fallback to vim.notify
|
||||||
|
vim.notify(message, level, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to show notifications specifically for dashboard
|
||||||
|
function M.show_dashboard_notification(message, level, opts)
|
||||||
|
-- In dashboard, show minimal notifications
|
||||||
|
local icon = "💬"
|
||||||
|
if level == vim.log.levels.ERROR then
|
||||||
|
icon = "❌"
|
||||||
|
elseif level == vim.log.levels.WARN then
|
||||||
|
icon = "⚠️"
|
||||||
|
elseif level == vim.log.levels.INFO then
|
||||||
|
icon = "ℹ️"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show message in status line or use echo
|
||||||
|
local short_message = message:sub(1, 50)
|
||||||
|
if #message > 50 then
|
||||||
|
short_message = short_message .. "..."
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Use echo for dashboard notifications to avoid overlapping
|
||||||
|
vim.cmd("echo '" .. icon .. " " .. short_message .. "'")
|
||||||
|
|
||||||
|
-- Clear message after a delay
|
||||||
|
vim.defer_fn(function()
|
||||||
|
vim.cmd("echo ''")
|
||||||
|
end, opts.timeout or 3000)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to clear all notifications
|
||||||
|
function M.clear_all_notifications()
|
||||||
|
for _, notif in ipairs(active_notifications) do
|
||||||
|
if notif.win and vim.api.nvim_win_is_valid(notif.win) then
|
||||||
|
vim.api.nvim_win_close(notif.win, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
active_notifications = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to show performance notification
|
||||||
|
function M.show_performance_notification(message, level)
|
||||||
|
M.show_notification("📊 " .. message, level, {
|
||||||
|
title = "Performance Monitor",
|
||||||
|
timeout = 4000,
|
||||||
|
position = "top_right",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to show LSP notification
|
||||||
|
function M.show_lsp_notification(message, level)
|
||||||
|
M.show_notification("🔧 " .. message, level, {
|
||||||
|
title = "LSP Status",
|
||||||
|
timeout = 3000,
|
||||||
|
position = "top_right",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to show file operation notification
|
||||||
|
function M.show_file_notification(message, level)
|
||||||
|
M.show_notification("📁 " .. message, level, {
|
||||||
|
title = "File Operation",
|
||||||
|
timeout = 2500,
|
||||||
|
position = "top_right",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to show plugin notification
|
||||||
|
function M.show_plugin_notification(message, level)
|
||||||
|
M.show_notification("🦥 " .. message, level, {
|
||||||
|
title = "Plugin Manager",
|
||||||
|
timeout = 3000,
|
||||||
|
position = "top_right",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to show startup notification
|
||||||
|
function M.show_startup_notification(message, level)
|
||||||
|
M.show_notification("🚀 " .. message, level, {
|
||||||
|
title = "Startup",
|
||||||
|
timeout = 2000,
|
||||||
|
position = "top_right",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to handle startup messages
|
||||||
|
function M.handle_startup_messages()
|
||||||
|
-- Clear any existing messages
|
||||||
|
vim.cmd("redraw!")
|
||||||
|
|
||||||
|
-- Suppress startup messages
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "I" -- No intro message
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "c" -- No completion messages
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "F" -- No file info message
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "W" -- No "written" message
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "A" -- No attention message
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "o" -- No overwrite messages
|
||||||
|
|
||||||
|
-- Clear any existing messages
|
||||||
|
vim.cmd("echo ''")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to setup notification system
|
||||||
|
function M.setup()
|
||||||
|
-- Create autocmd to handle startup messages
|
||||||
|
vim.api.nvim_create_autocmd("VimEnter", {
|
||||||
|
callback = function()
|
||||||
|
M.handle_startup_messages()
|
||||||
|
end,
|
||||||
|
once = true,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Create autocmd to handle alpha dashboard
|
||||||
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
|
pattern = "alpha",
|
||||||
|
callback = function()
|
||||||
|
M.handle_startup_messages()
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Override vim.notify to use our custom system
|
||||||
|
local original_notify = vim.notify
|
||||||
|
vim.notify = function(msg, level, opts)
|
||||||
|
M.show_notification(msg, level, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Notification manager initialized")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialize notification manager
|
||||||
|
M.setup()
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -4,6 +4,9 @@ require("cargdev.core.compatibility").setup()
|
|||||||
-- Load startup optimizations early
|
-- Load startup optimizations early
|
||||||
require("cargdev.core.startup_optimization")
|
require("cargdev.core.startup_optimization")
|
||||||
|
|
||||||
|
-- Load notification manager for better UX
|
||||||
|
require("cargdev.core.function.notification_manager")
|
||||||
|
|
||||||
require("cargdev.core.options")
|
require("cargdev.core.options")
|
||||||
require("cargdev.core.keymaps")
|
require("cargdev.core.keymaps")
|
||||||
|
|
||||||
|
|||||||
@@ -25,4 +25,8 @@ keymap.set("n", "<leader>pb", "<cmd>lua require('cargdev.core.function.performan
|
|||||||
|
|
||||||
-- LSP health and troubleshooting keymaps
|
-- LSP health and troubleshooting keymaps
|
||||||
keymap.set("n", "<leader>pl", "<cmd>lua require('cargdev.core.function.performance_monitor').check_lsp_health()<CR>", { desc = "Check LSP health" })
|
keymap.set("n", "<leader>pl", "<cmd>lua require('cargdev.core.function.performance_monitor').check_lsp_health()<CR>", { desc = "Check LSP health" })
|
||||||
keymap.set("n", "<leader>pr", "<cmd>lua require('cargdev.core.function.performance_monitor').restart_lsp()<CR>", { desc = "Restart LSP" })
|
keymap.set("n", "<leader>pr", "<cmd>lua require('cargdev.core.function.performance_monitor').restart_lsp()<CR>", { desc = "Restart LSP" })
|
||||||
|
|
||||||
|
-- Notification management keymaps
|
||||||
|
keymap.set("n", "<leader>nc", "<cmd>lua require('cargdev.core.function.notification_manager').clear_all_notifications()<CR>", { desc = "Clear all notifications" })
|
||||||
|
keymap.set("n", "<leader>nn", "<cmd>lua require('cargdev.core.function.notification_manager').show_notification('Test notification', vim.log.levels.INFO)<CR>", { desc = "Test notification" })
|
||||||
@@ -30,7 +30,7 @@ return {
|
|||||||
-- 📂 Set menu with improved icons and performance tools
|
-- 📂 Set menu with improved icons and performance tools
|
||||||
dashboard.section.buttons.val = {
|
dashboard.section.buttons.val = {
|
||||||
dashboard.button("f", "🔎 Find File (Safe)", "<cmd>Telescope find_files<CR>"),
|
dashboard.button("f", "🔎 Find File (Safe)", "<cmd>Telescope find_files<CR>"),
|
||||||
dashboard.button("n", "📜 New File", "<cmd>ene<CR>"),
|
dashboard.button("n", "📄 New File", "<cmd>ene<CR>"),
|
||||||
dashboard.button("g", "📝 Find Text", "<cmd>Telescope live_grep<CR>"),
|
dashboard.button("g", "📝 Find Text", "<cmd>Telescope live_grep<CR>"),
|
||||||
dashboard.button("r", "📚 Recent Files", "<cmd>Telescope oldfiles<CR>"),
|
dashboard.button("r", "📚 Recent Files", "<cmd>Telescope oldfiles<CR>"),
|
||||||
dashboard.button("c", "⚙️ Config", "<cmd>e ~/.config/nvim/init.lua<CR>"),
|
dashboard.button("c", "⚙️ Config", "<cmd>e ~/.config/nvim/init.lua<CR>"),
|
||||||
@@ -103,5 +103,42 @@ return {
|
|||||||
|
|
||||||
-- 🔥 Disable folding on alpha buffer
|
-- 🔥 Disable folding on alpha buffer
|
||||||
vim.cmd([[autocmd FileType alpha setlocal nofoldenable]])
|
vim.cmd([[autocmd FileType alpha setlocal nofoldenable]])
|
||||||
|
|
||||||
|
-- 🚫 Suppress startup messages that can overlap with dashboard
|
||||||
|
vim.api.nvim_create_autocmd("VimEnter", {
|
||||||
|
callback = function()
|
||||||
|
-- Clear any startup messages
|
||||||
|
vim.cmd("redraw!")
|
||||||
|
|
||||||
|
-- Suppress specific startup messages
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "I" -- No intro message
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "c" -- No completion messages
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "F" -- No file info message
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "W" -- No "written" message
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "A" -- No attention message
|
||||||
|
vim.opt.shortmess = vim.opt.shortmess + "o" -- No overwrite messages
|
||||||
|
|
||||||
|
-- Clear any existing messages
|
||||||
|
vim.cmd("echo ''")
|
||||||
|
end,
|
||||||
|
once = true,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- 🎨 Improve dashboard appearance and reduce overlapping
|
||||||
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
|
pattern = "alpha",
|
||||||
|
callback = function()
|
||||||
|
-- Set buffer options for better appearance
|
||||||
|
vim.opt_local.number = false
|
||||||
|
vim.opt_local.relativenumber = false
|
||||||
|
vim.opt_local.cursorline = false
|
||||||
|
vim.opt_local.cursorcolumn = false
|
||||||
|
vim.opt_local.signcolumn = "no"
|
||||||
|
vim.opt_local.foldcolumn = "0"
|
||||||
|
|
||||||
|
-- Clear any messages that might overlap
|
||||||
|
vim.cmd("redraw!")
|
||||||
|
end,
|
||||||
|
})
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,46 @@
|
|||||||
return {
|
return {
|
||||||
-- Enhanced notifications
|
-- Enhanced notifications with better positioning
|
||||||
{
|
{
|
||||||
"rcarriga/nvim-notify",
|
"rcarriga/nvim-notify",
|
||||||
event = "VeryLazy",
|
event = "VeryLazy",
|
||||||
config = function()
|
config = function()
|
||||||
vim.notify = require("notify")
|
vim.notify = require("notify")
|
||||||
|
|
||||||
|
-- Configure notifications to avoid overlapping
|
||||||
|
require("notify").setup({
|
||||||
|
-- Position notifications to avoid overlapping with dashboard
|
||||||
|
stages = "fade_in_slide_out",
|
||||||
|
timeout = 3000,
|
||||||
|
background_colour = "#000000",
|
||||||
|
max_width = 50,
|
||||||
|
max_height = 10,
|
||||||
|
default_timeout = 4000,
|
||||||
|
top_down = false, -- Show newer notifications at the bottom
|
||||||
|
render = "minimal",
|
||||||
|
minimum_width = 20,
|
||||||
|
icons = {
|
||||||
|
ERROR = " ",
|
||||||
|
WARN = " ",
|
||||||
|
INFO = " ",
|
||||||
|
DEBUG = " ",
|
||||||
|
TRACE = " ",
|
||||||
|
},
|
||||||
|
-- Position notifications away from dashboard
|
||||||
|
on_open = function(win)
|
||||||
|
-- Move notification window to avoid overlapping with alpha dashboard
|
||||||
|
local config = vim.api.nvim_win_get_config(win)
|
||||||
|
if config.relative == "editor" then
|
||||||
|
-- Position notifications in the top-right, but not overlapping dashboard
|
||||||
|
vim.api.nvim_win_set_config(win, {
|
||||||
|
row = 2,
|
||||||
|
col = vim.o.columns - 60, -- Position from right side
|
||||||
|
relative = "editor",
|
||||||
|
width = 55,
|
||||||
|
height = 8,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -126,7 +162,7 @@ return {
|
|||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Better completion menu
|
-- Better completion menu with improved positioning
|
||||||
{
|
{
|
||||||
"folke/noice.nvim",
|
"folke/noice.nvim",
|
||||||
event = "VeryLazy",
|
event = "VeryLazy",
|
||||||
@@ -156,6 +192,19 @@ return {
|
|||||||
},
|
},
|
||||||
view = "mini",
|
view = "mini",
|
||||||
},
|
},
|
||||||
|
-- Route startup messages to avoid overlapping with dashboard
|
||||||
|
{
|
||||||
|
filter = {
|
||||||
|
event = "msg_show",
|
||||||
|
any = {
|
||||||
|
{ find = "ideaDrop loaded!" },
|
||||||
|
{ find = "noice.nvim" },
|
||||||
|
{ find = "lazyredraw" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
view = "notify",
|
||||||
|
opts = { timeout = 2000 },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
presets = {
|
presets = {
|
||||||
bottom_search = true,
|
bottom_search = true,
|
||||||
@@ -163,6 +212,25 @@ return {
|
|||||||
long_message_to_split = true,
|
long_message_to_split = true,
|
||||||
inc_rename = true,
|
inc_rename = true,
|
||||||
},
|
},
|
||||||
|
-- Position command palette and other UI elements to avoid overlapping
|
||||||
|
cmdline = {
|
||||||
|
position = {
|
||||||
|
row = "50%",
|
||||||
|
col = "50%",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
popupmenu = {
|
||||||
|
position = {
|
||||||
|
row = "50%",
|
||||||
|
col = "50%",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
notify = {
|
||||||
|
-- Position notifications to avoid dashboard overlap
|
||||||
|
position = "top_right",
|
||||||
|
max_width = 50,
|
||||||
|
max_height = 10,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -175,6 +243,8 @@ return {
|
|||||||
theme = "auto",
|
theme = "auto",
|
||||||
globalstatus = true,
|
globalstatus = true,
|
||||||
disabled_filetypes = { statusline = { "dashboard", "alpha" } },
|
disabled_filetypes = { statusline = { "dashboard", "alpha" } },
|
||||||
|
component_separators = { left = "│", right = "│" },
|
||||||
|
section_separators = { left = "", right = "" },
|
||||||
},
|
},
|
||||||
sections = {
|
sections = {
|
||||||
lualine_a = { "mode" },
|
lualine_a = { "mode" },
|
||||||
|
|||||||
Reference in New Issue
Block a user