Add/Show/Delete Emojis on Notes (#181)

This MR adds the ability to view, add, and delete emojis from notes and comments.

This action can be performed by default with the `Ea` (emoji add) keybinding, and the `Ed` (emoji delete) keybinding. Only emojis added by the current user are eligible for deletion. The MR also implements a popup functionality which shows the user who added emojis on hover.

Implements #179
This commit is contained in:
Harrison (Harry) Cramer
2024-02-18 21:16:53 -05:00
committed by GitHub
parent 99741178f9
commit baee20b279
22 changed files with 11655 additions and 83 deletions

140
lua/gitlab/emoji.lua Normal file
View File

@@ -0,0 +1,140 @@
local u = require("gitlab.utils")
local state = require("gitlab.state")
local M = {
---@type EmojiMap|nil
emoji_map = {},
---@type Emoji[]
emoji_list = {},
}
M.init = function()
local bin_path = state.settings.bin_path
local emoji_path = bin_path
.. state.settings.file_separator
.. "config"
.. state.settings.file_separator
.. "emojis.json"
local emojis = u.read_file(emoji_path)
if emojis == nil then
u.notify("Could not read emoji file at " .. emoji_path, vim.log.levels.WARN)
end
local data_ok, data = pcall(vim.json.decode, emojis)
if not data_ok then
u.notify("Could not parse emoji file at " .. emoji_path, vim.log.levels.WARN)
end
M.emoji_map = data
M.emoji_list = {}
for _, v in pairs(M.emoji_map) do
table.insert(M.emoji_list, v)
end
end
-- Define the popup window options
M.popup_opts = {
relative = "cursor",
row = -2,
col = 0,
width = 2, -- Width set dynamically later
height = 1,
style = "minimal",
border = "single",
}
M.show_popup = function(char)
-- Close existing popup if it's open
if M.popup_win_id and vim.api.nvim_win_is_valid(M.popup_win_id) then
vim.api.nvim_win_close(M.popup_win_id, true)
end
-- Create a buffer for the popup window
local buf = vim.api.nvim_create_buf(false, true)
-- Set the content of the popup buffer to the character
vim.api.nvim_buf_set_lines(buf, 0, -1, false, { char })
-- Open the popup window and store its ID
M.popup_win_id = vim.api.nvim_open_win(buf, false, M.popup_opts)
end
M.close_popup = function()
if M.popup_win_id and vim.api.nvim_win_is_valid(M.popup_win_id) then
vim.api.nvim_win_close(M.popup_win_id, true)
M.popup_win_id = nil -- Reset the window ID
end
end
M.init_popup = function(tree, bufnr)
vim.api.nvim_create_autocmd({ "CursorHold" }, {
callback = function()
local node = tree:get_node()
if node == nil then
return
end
local note_node = require("gitlab.actions.discussions").get_note_node(tree, node)
local root_node = require("gitlab.actions.discussions").get_root_node(tree, node)
local note_id_str = tostring(note_node.is_root and root_node.root_note_id or note_node.id)
local emojis = require("gitlab.actions.discussions").emojis
local note_emojis = emojis[note_id_str]
if note_emojis == nil then
return
end
local cursor_pos = vim.api.nvim_win_get_cursor(0)
vim.api.nvim_command('normal! "zyiw')
vim.api.nvim_win_set_cursor(0, cursor_pos)
local word = vim.fn.getreg("z")
for k, v in pairs(M.emoji_map) do
if v.moji == word then
local names = M.get_users_who_reacted_with_emoji(k, note_emojis)
M.popup_opts.width = string.len(names)
if M.popup_opts.width > 0 then
M.show_popup(names)
end
end
end
end,
buffer = bufnr,
})
vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
callback = function()
M.close_popup()
end,
buffer = bufnr,
})
end
---@param name string
---@return string
M.get_users_who_reacted_with_emoji = function(name, note_emojis)
local result = ""
for _, v in pairs(note_emojis) do
if v.name == name then
result = result .. v.user.name .. ", "
end
end
return string.len(result) > 3 and result:sub(1, -3) or result
end
M.pick_emoji = function(options, cb)
vim.ui.select(options, {
prompt = "Choose emoji",
format_item = function(val)
return string.format("%s %s", val.moji, val.name)
end,
}, function(choice)
if not choice then
return
end
local name = choice.shortname:sub(2, -2)
cb(name, choice)
end)
end
return M