diff --git a/lua/cargdev/core/function/notification_manager.lua b/lua/cargdev/core/function/notification_manager.lua new file mode 100644 index 0000000..9a2c165 --- /dev/null +++ b/lua/cargdev/core/function/notification_manager.lua @@ -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 diff --git a/lua/cargdev/core/init.lua b/lua/cargdev/core/init.lua index c4ea358..c4f59b9 100644 --- a/lua/cargdev/core/init.lua +++ b/lua/cargdev/core/init.lua @@ -4,6 +4,9 @@ require("cargdev.core.compatibility").setup() -- Load startup optimizations early require("cargdev.core.startup_optimization") +-- Load notification manager for better UX +require("cargdev.core.function.notification_manager") + require("cargdev.core.options") require("cargdev.core.keymaps") diff --git a/lua/cargdev/core/keymaps/general.lua b/lua/cargdev/core/keymaps/general.lua index 4993227..df1894f 100644 --- a/lua/cargdev/core/keymaps/general.lua +++ b/lua/cargdev/core/keymaps/general.lua @@ -25,4 +25,8 @@ keymap.set("n", "pb", "lua require('cargdev.core.function.performan -- LSP health and troubleshooting keymaps keymap.set("n", "pl", "lua require('cargdev.core.function.performance_monitor').check_lsp_health()", { desc = "Check LSP health" }) -keymap.set("n", "pr", "lua require('cargdev.core.function.performance_monitor').restart_lsp()", { desc = "Restart LSP" }) \ No newline at end of file +keymap.set("n", "pr", "lua require('cargdev.core.function.performance_monitor').restart_lsp()", { desc = "Restart LSP" }) + +-- Notification management keymaps +keymap.set("n", "nc", "lua require('cargdev.core.function.notification_manager').clear_all_notifications()", { desc = "Clear all notifications" }) +keymap.set("n", "nn", "lua require('cargdev.core.function.notification_manager').show_notification('Test notification', vim.log.levels.INFO)", { desc = "Test notification" }) \ No newline at end of file diff --git a/lua/cargdev/plugins/alpha.lua b/lua/cargdev/plugins/alpha.lua index d0ad993..e43a816 100644 --- a/lua/cargdev/plugins/alpha.lua +++ b/lua/cargdev/plugins/alpha.lua @@ -30,7 +30,7 @@ return { -- 📂 Set menu with improved icons and performance tools dashboard.section.buttons.val = { dashboard.button("f", "🔎 Find File (Safe)", "Telescope find_files"), - dashboard.button("n", "📜 New File", "ene"), + dashboard.button("n", "📄 New File", "ene"), dashboard.button("g", "📝 Find Text", "Telescope live_grep"), dashboard.button("r", "📚 Recent Files", "Telescope oldfiles"), dashboard.button("c", "âš™ī¸ Config", "e ~/.config/nvim/init.lua"), @@ -103,5 +103,42 @@ return { -- đŸ”Ĩ Disable folding on alpha buffer 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, } diff --git a/lua/cargdev/plugins/essential_enhancements.lua b/lua/cargdev/plugins/essential_enhancements.lua index b89b22d..48fdb59 100644 --- a/lua/cargdev/plugins/essential_enhancements.lua +++ b/lua/cargdev/plugins/essential_enhancements.lua @@ -1,10 +1,46 @@ return { - -- Enhanced notifications + -- Enhanced notifications with better positioning { "rcarriga/nvim-notify", event = "VeryLazy", config = function() 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, }, @@ -126,7 +162,7 @@ return { end, }, - -- Better completion menu + -- Better completion menu with improved positioning { "folke/noice.nvim", event = "VeryLazy", @@ -156,6 +192,19 @@ return { }, 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 = { bottom_search = true, @@ -163,6 +212,25 @@ return { long_message_to_split = 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", globalstatus = true, disabled_filetypes = { statusline = { "dashboard", "alpha" } }, + component_separators = { left = "│", right = "│" }, + section_separators = { left = "", right = "" }, }, sections = { lualine_a = { "mode" },