From 169986a9659e7b04433db133dc0013d98e6c366a Mon Sep 17 00:00:00 2001 From: marcustyphoon Date: Sun, 16 Feb 2025 12:37:06 -0800 Subject: [PATCH] Meatballs util: Refactor; remove duplicate code (#1712) --- src/utils/meatballs.js | 96 +++++++++++++----------------------------- 1 file changed, 30 insertions(+), 66 deletions(-) diff --git a/src/utils/meatballs.js b/src/utils/meatballs.js index e4933a79f5..d7b0940d35 100644 --- a/src/utils/meatballs.js +++ b/src/utils/meatballs.js @@ -8,8 +8,10 @@ import { blogData, timelineObject } from './react_props.js'; const postHeaderSelector = `${postSelector} article > header`; const blogHeaderSelector = `[style*="--blog-title-color"] > div > div > header, ${keyToCss('blogCardHeaderBar')}`; -const meatballItems = {}; -const blogMeatballItems = {}; +const meatballItems = { + post: {}, + blog: {} +}; /** * Add a custom button to posts' meatball menus. @@ -20,13 +22,13 @@ const blogMeatballItems = {}; * @param {Function} [options.postFilter] - Filter function, called with the timelineObject data of the post element being actioned on. Must return true for button to be added */ export const registerMeatballItem = function ({ id, label, onclick, postFilter }) { - meatballItems[id] = { label, onclick, postFilter }; + meatballItems.post[id] = { label, onclick, filter: postFilter }; pageModifications.trigger(addMeatballItems); }; export const unregisterMeatballItem = id => { - delete meatballItems[id]; - $(`[data-xkit-meatball-button="${id}"]`).remove(); + delete meatballItems.post[id]; + $(`[data-xkit-post-meatball-button="${id}"]`).remove(); }; /** @@ -38,94 +40,56 @@ export const unregisterMeatballItem = id => { * @param {Function} [options.blogFilter] - Filter function, called with the blog data of the menu element being actioned on. Must return true for button to be added. Some blog data fields, such as "followed", are not available in blog cards. */ export const registerBlogMeatballItem = function ({ id, label, onclick, blogFilter }) { - blogMeatballItems[id] = { label, onclick, blogFilter }; + meatballItems.blog[id] = { label, onclick, filter: blogFilter }; pageModifications.trigger(addMeatballItems); }; export const unregisterBlogMeatballItem = id => { - delete blogMeatballItems[id]; + delete meatballItems.blog[id]; $(`[data-xkit-blog-meatball-button="${id}"]`).remove(); }; const addMeatballItems = meatballMenus => meatballMenus.forEach(async meatballMenu => { const inPostHeader = await inject('/main_world/test_header_element.js', [postHeaderSelector], meatballMenu); if (inPostHeader) { - addPostMeatballItem(meatballMenu); + addTypedMeatballItems({ + meatballMenu, + type: 'post', + reactData: await timelineObject(meatballMenu), + reactDataKey: '__timelineObjectData' + }); return; } const inBlogHeader = await inject('/main_world/test_header_element.js', [blogHeaderSelector], meatballMenu); if (inBlogHeader) { - addBlogMeatballItem(meatballMenu); + addTypedMeatballItems({ + meatballMenu, + type: 'blog', + reactData: await blogData(meatballMenu), + reactDataKey: '__blogData' + }); } }); -const addPostMeatballItem = async meatballMenu => { - const __timelineObjectData = await timelineObject(meatballMenu); - - $(meatballMenu).children('[data-xkit-meatball-button]').remove(); - - Object.keys(meatballItems).sort().forEach(id => { - const { label, onclick, postFilter } = meatballItems[id]; - - const meatballItemButton = dom('button', { - class: 'xkit-meatball-button', - 'data-xkit-meatball-button': id, - hidden: true - }, { - click: onclick - }, [ - '\u22EF' - ]); - meatballItemButton.__timelineObjectData = __timelineObjectData; - - if (label instanceof Function) { - const labelResult = label(__timelineObjectData); - - if (labelResult instanceof Promise) { - labelResult.then(result => { meatballItemButton.textContent = result; }); - } else { - meatballItemButton.textContent = labelResult; - } - } else { - meatballItemButton.textContent = label; - } - - if (postFilter instanceof Function) { - const shouldShowItem = postFilter(__timelineObjectData); - meatballItemButton.hidden = shouldShowItem !== true; - - if (shouldShowItem instanceof Promise) { - shouldShowItem.then(result => { meatballItemButton.hidden = result !== true; }); - } - } else { - meatballItemButton.hidden = false; - } - - meatballMenu.append(meatballItemButton); - }); -}; - -const addBlogMeatballItem = async meatballMenu => { - const __blogData = await blogData(meatballMenu); - - $(meatballMenu).children('[data-xkit-blog-meatball-button]').remove(); +const addTypedMeatballItems = async ({ meatballMenu, type, reactData, reactDataKey }) => { + $(meatballMenu).children(`[data-xkit-${type}-meatball-button]`).remove(); - Object.keys(blogMeatballItems).sort().forEach(id => { - const { label, onclick, blogFilter } = blogMeatballItems[id]; + Object.keys(meatballItems[type]).sort().forEach(id => { + const { label, onclick, filter } = meatballItems[type][id]; const meatballItemButton = dom('button', { class: 'xkit-meatball-button', - 'data-xkit-blog-meatball-button': id, + [`data-xkit-${type}-meatball-button`]: id, hidden: true }, { click: onclick }, [ '\u22EF' ]); - meatballItemButton.__blogData = __blogData; + meatballItemButton[reactDataKey] = reactData; if (label instanceof Function) { - const labelResult = label(__blogData); + const labelResult = label(reactData); if (labelResult instanceof Promise) { labelResult.then(result => { meatballItemButton.textContent = result; }); @@ -136,8 +100,8 @@ const addBlogMeatballItem = async meatballMenu => { meatballItemButton.textContent = label; } - if (blogFilter instanceof Function) { - const shouldShowItem = blogFilter(__blogData); + if (filter instanceof Function) { + const shouldShowItem = filter(reactData); meatballItemButton.hidden = shouldShowItem !== true; if (shouldShowItem instanceof Promise) {