Skip to content

Commit

Permalink
feat(notifications): show and read unread notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
tris203 committed Nov 24, 2024
1 parent 51f1808 commit 1133398
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 1 deletion.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ require"octo".setup({
close_review_tab = { lhs = "<C-c>", desc = "close review tab" },
toggle_viewed = { lhs = "<localleader><space>", desc = "toggle viewer viewed state" },
},
notification = {
read_notification = { lhs = "<localleader>rn", desc = "mark notification as read" },
},
},
})
```
Expand Down Expand Up @@ -369,6 +372,7 @@ If no command is passed, the argument to `Octo` is treated as a URL from where a
| | close | Close the review window and return to the PR |
| actions | | Lists all available Octo actions |
| search | <query> | Search GitHub for issues and PRs matching the [query](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests) |
| notification | | Shows current unread notifications |

0. `[repo]`: If repo is not provided, it will be derived from `<cwd>/.git/config`.

Expand Down
3 changes: 3 additions & 0 deletions lua/octo/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@ function M.setup()
M.remove_project_card()
end,
},
notification = function()
picker.notifications()
end,
}

setmetatable(M.commands.pr, {
Expand Down
5 changes: 4 additions & 1 deletion lua/octo/config.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
local vim = vim
local M = {}

---@alias OctoMappingsWindow "issue" | "pull_request" | "review_thread" | "submit_win" | "review_diff" | "file_panel" | "repo"
---@alias OctoMappingsWindow "issue" | "pull_request" | "review_thread" | "submit_win" | "review_diff" | "file_panel" | "repo" | "notification"
---@alias OctoMappingsList { [string]: table}
---@alias OctoPickers "telescope" | "fzf-lua"
---@alias OctoFocus "right" | "left"
Expand Down Expand Up @@ -291,6 +291,9 @@ function M.get_default_values()
close_review_tab = { lhs = "<C-c>", desc = "close review tab" },
toggle_viewed = { lhs = "<localleader><space>", desc = "toggle viewer viewed state" },
},
notification = {
read_notification = { lhs = "<localleader>nr", desc = "mark notification as read" },
},
repo = {},
},
}
Expand Down
72 changes: 72 additions & 0 deletions lua/octo/pickers/telescope/entry_maker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ local icons = {
merged = { "", "OctoPurple" },
closed = { "", "OctoRed" },
},
notification = {
issue = {
unread = { "", "OctoBlue" },
read = { "", "OctoGrey" },
},
pull_request = {
unread = { "", "OctoBlue" },
read = { "", "OctoGrey" },
},
unknown = {
unread = { "", "OctoBlue" },
read = { "", "OctoGrey" },
},
},
unknown = { "" },
}

Expand Down Expand Up @@ -614,6 +628,64 @@ function M.gen_from_octo_actions()
end
end

function M.gen_from_notification()
local make_display = function(entry)
if not entry then
return nil
end

local columns = {
entry.obj.unread == true and icons.notification[entry.kind].unread or icons.notification[entry.kind].read,
{ "#" .. (entry.obj.subject.url:match "/(%d+)$" or "NA") },
{ string.sub(entry.obj.repository.full_name, 1, 50), "TelescopeResultsNumber" },
{ string.sub(entry.obj.subject.title, 1, 100) },
}

local displayer = entry_display.create {
separator = " ",
items = {
{ width = 2 },
{ width = 12 },
{ width = math.min(#entry.obj.repository.full_name, 50) },
{ width = math.min(#entry.obj.subject.title, 100) },
},
}

return displayer(columns)
end

return function(notification)
if not notification or vim.tbl_isempty(notification) then
return nil
end

notification.kind = (function(type)
if type == "Issue" then
return "issue"
elseif type == "PullRequest" then
return "pull_request"
end
return "unknown"
end)(notification.subject.type)

if notification.kind == "unknown" then
return nil
end
local ref = notification.subject.url:match "/(%d+)$"

return {
value = ref,
ordinal = notification.subject.title .. " " .. notification.repository.full_name .. " " .. ref,
display = make_display,
obj = notification,
repo = notification.repository.full_name,
kind = notification.kind,
thread_id = notification.id,
url = notification.subject.url,
}
end
end

function M.gen_from_issue_templates()
local make_display = function(entry)
if not entry then
Expand Down
64 changes: 64 additions & 0 deletions lua/octo/pickers/telescope/provider.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,69 @@ function M.actions(flattened_actions)
:find()
end

--
-- NOTIFICATIONS
--
local function mark_notification_read()
return function(prompt_bufnr)
local current_picker = action_state.get_current_picker(prompt_bufnr)
current_picker:delete_selection(function(selection)
local url = string.format("/notifications/threads/%s", selection.thread_id)
gh.run {
args = { "api", "--method", "PATCH", url },
headers = { "Accept: application/vnd.github.v3.diff" },
cb = function(_, stderr)
if stderr and not utils.is_blank(stderr) then
utils.error(stderr)
return
end
end,
}
end)
end
end

function M.notifications()
local cfg = octo_config.values
local opts = {
preview_title = "",
prompt_title = "Github Notifications",
results_title = "",
}

gh.run {
args = { "api", "--paginate", "/notifications" },
headers = { "Accept: application/vnd.github.v3.diff" },
cb = function(output, stderr)
if stderr and not utils.is_blank(stderr) then
utils.error(stderr)
elseif output then
local resp = vim.fn.json_decode(output)
pickers
.new(opts, {

finder = finders.new_table {
results = resp,
entry_maker = entry_maker.gen_from_notification(),
},
sorter = conf.generic_sorter(opts),
previewer = previewers.issue.new(opts),
attach_mappings = function(_, map)
action_set.select:replace(function(prompt_bufnr, type)
open(type)(prompt_bufnr)
end)
map("i", cfg.picker_config.mappings.open_in_browser.lhs, open_in_browser())
map("i", cfg.picker_config.mappings.copy_url.lhs, copy_url())
map("i", cfg.mappings.notification.read_notification.lhs, mark_notification_read())
return true
end,
})
:find()
end
end,
}
end

--
-- Issue templates
--
Expand Down Expand Up @@ -1149,6 +1212,7 @@ M.picker = {
search = M.search,
actions = M.actions,
issue_templates = M.issue_templates,
notifications = M.notifications,
}

return M

0 comments on commit 1133398

Please sign in to comment.