From 85ac2c179fb6282e1f73f7efef78581a270f8527 Mon Sep 17 00:00:00 2001 From: Jaeyeol Lee Date: Wed, 28 Dec 2022 00:36:33 +0900 Subject: [PATCH 1/5] Refactor renderer functions * Extract duplicated codes into local function --- lua/mastodon/renderer.lua | 80 +++++---------------------------------- 1 file changed, 9 insertions(+), 71 deletions(-) diff --git a/lua/mastodon/renderer.lua b/lua/mastodon/renderer.lua index 1195c3f..72a6340 100644 --- a/lua/mastodon/renderer.lua +++ b/lua/mastodon/renderer.lua @@ -244,7 +244,7 @@ local function prepare_statuses(statuses, width) } end -M.render_home_timeline = function(bufnr, win, statuses) +local function render_statuses(bufnr, win, statuses, buf_name) local namespaces = vim.api.nvim_get_namespaces() local mastodon_ns = namespaces['MastodonNS'] @@ -254,7 +254,7 @@ M.render_home_timeline = function(bufnr, win, statuses) local line_numbers = result.line_numbers local metadata = result.metadata - vim.api.nvim_buf_set_name(bufnr, "Mastodon Home") + vim.api.nvim_buf_set_name(bufnr, buf_name) vim.api.nvim_buf_set_option(bufnr, "filetype", "mastodon") vim.api.nvim_buf_set_lines(0, 0, 0, 'true', lines) vim.api.nvim_win_set_hl_ns(win, mastodon_ns) @@ -270,82 +270,20 @@ M.render_home_timeline = function(bufnr, win, statuses) end end -M.render_bookmarks = function(bufnr, win, statuses) - local namespaces = vim.api.nvim_get_namespaces() - local mastodon_ns = namespaces['MastodonNS'] - - local width = vim.api.nvim_win_get_width(win) - local result = prepare_statuses(statuses, width) - local lines = result.lines - local line_numbers = result.line_numbers - local metadata = result.metadata - - vim.api.nvim_buf_set_name(bufnr, "Mastodon Bookmark") - vim.api.nvim_buf_set_option(bufnr, "filetype", "mastodon") - vim.api.nvim_buf_set_lines(0, 0, 0, 'true', lines) - vim.api.nvim_win_set_hl_ns(win, mastodon_ns) - - for _, line_number in ipairs(line_numbers) do - vim.api.nvim_buf_add_highlight(bufnr, mastodon_ns, "MastodonHandle", line_number, 0, -1) - end +M.render_home_timeline = function(bufnr, win, statuses) + render_statuses(bufnr, win, statuses, "Mastodon Home") +end - for _, metadata_for_line in ipairs(metadata) do - vim.api.nvim_buf_set_extmark(bufnr, mastodon_ns, metadata_for_line.line_number, 0, { - virt_text = {{metadata_for_line.data, "Whitespace"}}, - }) - end +M.render_bookmarks = function(bufnr, win, statuses) + render_statuses(bufnr, win, statuses, "Mastodon Bookmark") end M.render_favourites = function(bufnr, win, statuses) - local namespaces = vim.api.nvim_get_namespaces() - local mastodon_ns = namespaces['MastodonNS'] - - local width = vim.api.nvim_win_get_width(win) - local result = prepare_statuses(statuses, width) - local lines = result.lines - local line_numbers = result.line_numbers - local metadata = result.metadata - - vim.api.nvim_buf_set_name(bufnr, "Mastodon Favourites") - vim.api.nvim_buf_set_option(bufnr, "filetype", "mastodon") - vim.api.nvim_buf_set_lines(0, 0, 0, 'true', lines) - vim.api.nvim_win_set_hl_ns(win, mastodon_ns) - - for _, line_number in ipairs(line_numbers) do - vim.api.nvim_buf_add_highlight(bufnr, mastodon_ns, "MastodonHandle", line_number, 0, -1) - end - - for _, metadata_for_line in ipairs(metadata) do - vim.api.nvim_buf_set_extmark(bufnr, mastodon_ns, metadata_for_line.line_number, 0, { - virt_text = {{metadata_for_line.data, "Whitespace"}}, - }) - end + render_statuses(bufnr, win, statuses, "Mastodon Favourites") end M.render_replies = function(bufnr, win, statuses) - local namespaces = vim.api.nvim_get_namespaces() - local mastodon_ns = namespaces['MastodonNS'] - - local width = vim.api.nvim_win_get_width(win) - local result = prepare_statuses(statuses, width) - local lines = result.lines - local line_numbers = result.line_numbers - local metadata = result.metadata - - vim.api.nvim_buf_set_name(bufnr, "Mastodon Replies") - vim.api.nvim_buf_set_option(bufnr, "filetype", "mastodon") - vim.api.nvim_buf_set_lines(0, 0, 0, 'true', lines) - vim.api.nvim_win_set_hl_ns(win, mastodon_ns) - - for _, line_number in ipairs(line_numbers) do - vim.api.nvim_buf_add_highlight(bufnr, mastodon_ns, "MastodonHandle", line_number, 0, -1) - end - - for _, metadata_for_line in ipairs(metadata) do - vim.api.nvim_buf_set_extmark(bufnr, mastodon_ns, metadata_for_line.line_number, 0, { - virt_text = {{metadata_for_line.data, "Whitespace"}}, - }) - end + render_statuses(bufnr, win, statuses, "Mastodon Replies") end M.flatten_nodes = flatten_nodes From d2d7dada502b5a8394014fd7291ba3ab00481e04 Mon Sep 17 00:00:00 2001 From: Jaeyeol Lee Date: Wed, 28 Dec 2022 01:08:49 +0900 Subject: [PATCH 2/5] Introduce mode option to renderer functions (prepend/append) --- lua/mastodon/renderer.lua | 48 +++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/lua/mastodon/renderer.lua b/lua/mastodon/renderer.lua index 72a6340..7496e27 100644 --- a/lua/mastodon/renderer.lua +++ b/lua/mastodon/renderer.lua @@ -244,7 +244,7 @@ local function prepare_statuses(statuses, width) } end -local function render_statuses(bufnr, win, statuses, buf_name) +local function render_statuses(bufnr, win, statuses, buf_name, mode) local namespaces = vim.api.nvim_get_namespaces() local mastodon_ns = namespaces['MastodonNS'] @@ -254,36 +254,60 @@ local function render_statuses(bufnr, win, statuses, buf_name) local line_numbers = result.line_numbers local metadata = result.metadata + local offset = 0 vim.api.nvim_buf_set_name(bufnr, buf_name) vim.api.nvim_buf_set_option(bufnr, "filetype", "mastodon") - vim.api.nvim_buf_set_lines(0, 0, 0, 'true', lines) + if mode == "prepend" then + offset = 0 + vim.api.nvim_buf_set_lines(bufnr, 0, 0, 'true', lines) + elseif mode == "append" then + offset = vim.api.nvim_buf_line_count(bufnr) + vim.api.nvim_buf_set_lines(bufnr, -1, -1, 'true', lines) + end + vim.api.nvim_win_set_hl_ns(win, mastodon_ns) for _, line_number in ipairs(line_numbers) do - vim.api.nvim_buf_add_highlight(bufnr, mastodon_ns, "MastodonHandle", line_number, 0, -1) + vim.api.nvim_buf_add_highlight(bufnr, mastodon_ns, "MastodonHandle", offset + line_number, 0, -1) end for _, metadata_for_line in ipairs(metadata) do - vim.api.nvim_buf_set_extmark(bufnr, mastodon_ns, metadata_for_line.line_number, 0, { + vim.api.nvim_buf_set_extmark(bufnr, mastodon_ns, offset + metadata_for_line.line_number, 0, { virt_text = {{metadata_for_line.data, "Whitespace"}}, }) end end -M.render_home_timeline = function(bufnr, win, statuses) - render_statuses(bufnr, win, statuses, "Mastodon Home") +M.render_home_timeline = function(bufnr, win, statuses, options) + local mode = "prepend" + if options ~= nil then + mode = options.mode + end + render_statuses(bufnr, win, statuses, "Mastodon Home", mode) end -M.render_bookmarks = function(bufnr, win, statuses) - render_statuses(bufnr, win, statuses, "Mastodon Bookmark") +M.render_bookmarks = function(bufnr, win, statuses, options) + local mode = "prepend" + if options ~= nil then + mode = options.mode + end + render_statuses(bufnr, win, statuses, "Mastodon Bookmark", mode) end -M.render_favourites = function(bufnr, win, statuses) - render_statuses(bufnr, win, statuses, "Mastodon Favourites") +M.render_favourites = function(bufnr, win, statuses, options) + local mode = "prepend" + if options ~= nil then + mode = options.mode + end + render_statuses(bufnr, win, statuses, "Mastodon Favourites", mode) end -M.render_replies = function(bufnr, win, statuses) - render_statuses(bufnr, win, statuses, "Mastodon Replies") +M.render_replies = function(bufnr, win, statuses, options) + local mode = "prepend" + if options ~= nil then + mode = options.mode + end + render_statuses(bufnr, win, statuses, "Mastodon Replies", mode) end M.flatten_nodes = flatten_nodes From 78e3b31f3114eaff22db2470cfa7281887bf91dc Mon Sep 17 00:00:00 2001 From: Jaeyeol Lee Date: Tue, 27 Dec 2022 14:31:52 +0900 Subject: [PATCH 3/5] feat: Support Home Timeline navigation --- lua/mastodon/api_client.lua | 16 ++++++- lua/mastodon/commands.lua | 95 ++++++++++++++++++++++++++++++++++++- plugin/mastodon.lua | 2 + 3 files changed, 110 insertions(+), 3 deletions(-) diff --git a/lua/mastodon/api_client.lua b/lua/mastodon/api_client.lua index 760c28c..0f2383a 100644 --- a/lua/mastodon/api_client.lua +++ b/lua/mastodon/api_client.lua @@ -51,9 +51,22 @@ M.get_status = function(status_id) return status end -M.fetch_home_timeline = function() +M.fetch_home_timeline = function(params) local active_accounts = db_client:get_active_account() local active_account = active_accounts[1] + local query = {} + + if params.since_id ~= nil then + query.since_id = params.since_id + end + + if params.max_id ~= nil then + query.max_id = params.max_id + end + + if params.min_id ~= nil then + query.min_id = params.min_id + end local access_token = active_account.access_token local instance_url = active_account.instance_url @@ -61,6 +74,7 @@ M.fetch_home_timeline = function() local url = instance_url .. "/api/v1/timelines/home" local res = curl.get(url, { + query = query, headers = { accept = "application/json", content_type = "application/json", diff --git a/lua/mastodon/commands.lua b/lua/mastodon/commands.lua index b2e6387..20eb02f 100644 --- a/lua/mastodon/commands.lua +++ b/lua/mastodon/commands.lua @@ -96,7 +96,7 @@ end M.fetch_home_timeline = function() - local statuses = api_client.fetch_home_timeline() + local statuses = api_client.fetch_home_timeline({}) local bufnr = 0 local buf = nil local target_buf_name = "Mastodon Home" @@ -117,6 +117,23 @@ M.fetch_home_timeline = function() bufnr = vim.api.nvim_get_current_buf() renderer.render_home_timeline(bufnr, win, statuses) + local max_status_id = nil + local min_status_id = nil + max_status_id = statuses[1]["id"] + min_status_id = statuses[#statuses]["id"] + + if max_status_id ~= nil then + if vim.b[bufnr].max_status_id == nil then + vim.b[bufnr].max_status_id = max_status_id + end + end + + if min_status_id ~= nil then + if vim.b[bufnr].min_status_id == nil then + vim.b[bufnr].min_status_id = min_status_id + end + end + vim.api.nvim_win_set_cursor(0, {1, 0}) end @@ -207,9 +224,26 @@ M.reload_statuses = function() vim.api.nvim_buf_delete(bufnr, {}) bufnr = new_buf - local statuses = api_client.fetch_home_timeline() + local statuses = api_client.fetch_home_timeline({}) renderer.render_home_timeline(bufnr, win, statuses) + local max_status_id = nil + local min_status_id = nil + max_status_id = statuses[1]["id"] + min_status_id = statuses[#statuses]["id"] + + if max_status_id ~= nil then + if vim.b[bufnr].max_status_id == nil then + vim.b[bufnr].max_status_id = max_status_id + end + end + + if min_status_id ~= nil then + if vim.b[bufnr].min_status_id == nil then + vim.b[bufnr].min_status_id = min_status_id + end + end + vim.api.nvim_win_set_cursor(0, {1, 0}) elseif string.find(buf_name, "Mastodon Bookmark") then local new_buf = vim.api.nvim_create_buf(true, true) @@ -244,4 +278,61 @@ M.reload_statuses = function() end end + +M.fetch_older_statuses = function() + local win = vim.api.nvim_get_current_win() + local bufnr = vim.api.nvim_get_current_buf() + local min_status_id = vim.b[bufnr].min_status_id + + local buf_name = vim.api.nvim_buf_get_name(bufnr) + local fetch_statuses = api_client.fetch_home_timeline + local render_statuses = renderer.render_home_timeline + + if string.find(buf_name, "Mastodon Home") then + fetch_statuses = api_client.fetch_home_timeline + render_statuses = renderer.render_home_timeline + end + + if string.find(buf_name, "Mastodon") then + local statuses = fetch_statuses({ max_id = min_status_id }) + if #statuses > 0 then + min_status_id = statuses[#statuses]["id"] + + if min_status_id ~= nil then + vim.b[bufnr].min_status_id = min_status_id + end + end + + render_statuses(bufnr, win, statuses, { mode = "append" }) + end +end + +M.fetch_newer_statuses = function() + local win = vim.api.nvim_get_current_win() + local bufnr = vim.api.nvim_get_current_buf() + local max_status_id = vim.b[bufnr].max_status_id + + local buf_name = vim.api.nvim_buf_get_name(bufnr) + local fetch_statuses = api_client.fetch_home_timeline + local render_statuses = renderer.render_home_timeline + + if string.find(buf_name, "Mastodon Home") then + fetch_statuses = api_client.fetch_home_timeline + render_statuses = renderer.render_home_timeline + end + + if string.find(buf_name, "Mastodon") then + local statuses = fetch_statuses({ min_id = max_status_id }) + if #statuses > 0 then + max_status_id = statuses[1]["id"] + + if max_status_id ~= nil then + vim.b[bufnr].max_status_id = max_status_id + end + end + + render_statuses(bufnr, win, statuses, { mode = "prepend" }) + end +end + return M diff --git a/plugin/mastodon.lua b/plugin/mastodon.lua index a753d56..ecc4438 100644 --- a/plugin/mastodon.lua +++ b/plugin/mastodon.lua @@ -21,6 +21,8 @@ vim.api.nvim_create_autocmd('FileType', { -- if keymap starts with `,m`, -- buffer-wide or system-wide commands should be called map('n', ',mr', ":lua require('mastodon').reload_statuses()", default_opts) + map('n', ',mk', ":lua require('mastodon.commands').fetch_newer_statuses()", default_opts) + map('n', ',mj', ":lua require('mastodon.commands').fetch_older_statuses()", default_opts) -- If keymap starts with `,t` -- status-wide commands should be called From db1657aa0dc9752de1a9fe4c0c58ca146d048f0b Mon Sep 17 00:00:00 2001 From: Jaeyeol Lee Date: Sat, 31 Dec 2022 00:28:39 +0900 Subject: [PATCH 4/5] fix: Navigating is only available in Home Timeline Favourites, Bookmarks different paginations using Link header See: https://docs.joinmastodon.org/api/guidelines/#pagination --- lua/mastodon/commands.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/mastodon/commands.lua b/lua/mastodon/commands.lua index 20eb02f..805df06 100644 --- a/lua/mastodon/commands.lua +++ b/lua/mastodon/commands.lua @@ -293,7 +293,7 @@ M.fetch_older_statuses = function() render_statuses = renderer.render_home_timeline end - if string.find(buf_name, "Mastodon") then + if string.find(buf_name, "Mastodon Home") then local statuses = fetch_statuses({ max_id = min_status_id }) if #statuses > 0 then min_status_id = statuses[#statuses]["id"] @@ -321,7 +321,7 @@ M.fetch_newer_statuses = function() render_statuses = renderer.render_home_timeline end - if string.find(buf_name, "Mastodon") then + if string.find(buf_name, "Mastodon Home") then local statuses = fetch_statuses({ min_id = max_status_id }) if #statuses > 0 then max_status_id = statuses[1]["id"] From ff3fa0ebb7db0ef1e0e0c368146ffc803453ff8d Mon Sep 17 00:00:00 2001 From: Jaeyeol Lee Date: Tue, 3 Jan 2023 04:52:22 +0900 Subject: [PATCH 5/5] Introduce scroll utility function (`scroll_to_top`, `scroll_to_bottom`) --- lua/mastodon/commands.lua | 16 ---------------- lua/mastodon/renderer.lua | 6 ++++++ lua/mastodon/utils.lua | 9 +++++++++ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/lua/mastodon/commands.lua b/lua/mastodon/commands.lua index 805df06..e5a379f 100644 --- a/lua/mastodon/commands.lua +++ b/lua/mastodon/commands.lua @@ -133,8 +133,6 @@ M.fetch_home_timeline = function() vim.b[bufnr].min_status_id = min_status_id end end - - vim.api.nvim_win_set_cursor(0, {1, 0}) end M.fetch_bookmarks = function() @@ -158,8 +156,6 @@ M.fetch_bookmarks = function() bufnr = vim.api.nvim_get_current_buf() renderer.render_bookmarks(bufnr, win, statuses) - - vim.api.nvim_win_set_cursor(0, {1, 0}) end M.fetch_favourites = function() @@ -183,8 +179,6 @@ M.fetch_favourites = function() bufnr = vim.api.nvim_get_current_buf() renderer.render_favourites(bufnr, win, statuses) - - vim.api.nvim_win_set_cursor(0, {1, 0}) end M.fetch_replies = function() @@ -208,8 +202,6 @@ M.fetch_replies = function() bufnr = vim.api.nvim_get_current_buf() renderer.render_replies(bufnr, win, statuses) - - vim.api.nvim_win_set_cursor(0, {1, 0}) end M.reload_statuses = function() @@ -243,8 +235,6 @@ M.reload_statuses = function() vim.b[bufnr].min_status_id = min_status_id end end - - vim.api.nvim_win_set_cursor(0, {1, 0}) elseif string.find(buf_name, "Mastodon Bookmark") then local new_buf = vim.api.nvim_create_buf(true, true) vim.api.nvim_win_set_buf(win, new_buf) @@ -253,8 +243,6 @@ M.reload_statuses = function() local statuses = api_client.fetch_bookmarks() renderer.render_bookmarks(bufnr, win, statuses) - - vim.api.nvim_win_set_cursor(0, {1, 0}) elseif string.find(buf_name, "Mastodon Favourites") then local new_buf = vim.api.nvim_create_buf(true, true) vim.api.nvim_win_set_buf(win, new_buf) @@ -263,8 +251,6 @@ M.reload_statuses = function() local statuses = api_client.fetch_favourites() renderer.render_favourites(bufnr, win, statuses) - - vim.api.nvim_win_set_cursor(0, {1, 0}) elseif string.find(buf_name, "Mastodon Replies") then local new_buf = vim.api.nvim_create_buf(true, true) vim.api.nvim_win_set_buf(win, new_buf) @@ -273,8 +259,6 @@ M.reload_statuses = function() local statuses = api_client.fetch_replies() renderer.render_favourites(bufnr, win, statuses) - - vim.api.nvim_win_set_cursor(0, {1, 0}) end end diff --git a/lua/mastodon/renderer.lua b/lua/mastodon/renderer.lua index 7496e27..db5c98a 100644 --- a/lua/mastodon/renderer.lua +++ b/lua/mastodon/renderer.lua @@ -276,6 +276,12 @@ local function render_statuses(bufnr, win, statuses, buf_name, mode) virt_text = {{metadata_for_line.data, "Whitespace"}}, }) end + + if mode == "prepend" then + utils.scroll_to_top() + elseif mode == "append" then + utils.scroll_to_bottom() + end end M.render_home_timeline = function(bufnr, win, statuses, options) diff --git a/lua/mastodon/utils.lua b/lua/mastodon/utils.lua index 802386d..199ab77 100644 --- a/lua/mastodon/utils.lua +++ b/lua/mastodon/utils.lua @@ -4,6 +4,15 @@ M.trim = function(s) return (string.gsub(s, "^%s*(.-)%s*$", "%1")) end +M.scroll_to_top = function() + vim.api.nvim_win_set_cursor(0, {1, 0}) +end + +M.scroll_to_bottom = function() + local target = vim.api.nvim_buf_line_count(0) + vim.api.nvim_win_set_cursor(0, {target, 0}) +end + M.execute_curl = function(curl_command) local handle = io.popen(curl_command, 'r') local response = handle:read("*a")