From 5521e39a66d41d06c55b475b6737a2cab2dd60df Mon Sep 17 00:00:00 2001 From: cottongin Date: Wed, 26 Aug 2026 21:14:06 -0400 Subject: [PATCH] feat: add card layout tweak with unified post observer Co-authored-by: Cursor --- content/main.js | 71 +++++++++++++++++++++++++++++++++++++++- content/tweaks/badges.js | 51 +---------------------------- content/tweaks/cards.js | 59 +++++++++++++++++++++++++++++++++ manifest.json | 3 +- 4 files changed, 132 insertions(+), 52 deletions(-) create mode 100644 content/tweaks/cards.js diff --git a/content/main.js b/content/main.js index 42c6dea..4b86c4f 100644 --- a/content/main.js +++ b/content/main.js @@ -1,6 +1,62 @@ (function () { "use strict"; + function startDarkModeObserver(settings) { + var observer = new MutationObserver(function () { + if (settings.darkMode === "auto") { + window.RedditTweaks.loadSettings().then(function (updated) { + if (settings.badgeLayout) { + window.RedditTweaks.badgeTweak.updateColors(updated); + } + if (settings.cardLayout) { + window.RedditTweaks.cardTweak.updateSettings(updated); + } + }); + } + }); + + observer.observe(document.body, { + attributes: true, + attributeFilter: ["class"], + }); + } + + function startPostObserver(settings) { + var target = + document.getElementById("siteTable") || + document.querySelector('.content[role="main"]') || + document.body; + + var observer = new MutationObserver(function (mutations) { + var hasNewPosts = false; + for (var i = 0; i < mutations.length; i++) { + var added = mutations[i].addedNodes; + for (var j = 0; j < added.length; j++) { + var node = added[j]; + if (node.nodeType !== Node.ELEMENT_NODE) continue; + if ((node.matches && node.matches("div.thing.link")) || + (node.querySelector && node.querySelector("div.thing.link"))) { + hasNewPosts = true; + break; + } + } + if (hasNewPosts) break; + } + if (hasNewPosts) { + window.RedditTweaks.loadSettings().then(function (updated) { + if (settings.badgeLayout) { + window.RedditTweaks.badgeTweak.processNewPosts(updated); + } + if (settings.cardLayout) { + window.RedditTweaks.cardTweak.processNewPosts(updated); + } + }); + } + }); + + observer.observe(target, { childList: true, subtree: true }); + } + async function init() { const settings = await window.RedditTweaks.loadSettings(); if (!settings.enabled) return; @@ -10,10 +66,20 @@ window.RedditTweaks.badgeTweak.apply(settings); } + if (settings.cardLayout) { + window.RedditTweaks.cardTweak.apply(settings); + } + + if (settings.badgeLayout || settings.cardLayout) { + startPostObserver(settings); + startDarkModeObserver(settings); + } + browser.storage.onChanged.addListener(function (changes) { if ( (changes.enabled && changes.enabled.newValue !== changes.enabled.oldValue) || - (changes.badgeLayout && changes.badgeLayout.newValue !== changes.badgeLayout.oldValue) + (changes.badgeLayout && changes.badgeLayout.newValue !== changes.badgeLayout.oldValue) || + (changes.cardLayout && changes.cardLayout.newValue !== changes.cardLayout.oldValue) ) { location.reload(); return; @@ -23,6 +89,9 @@ if (settings.badgeLayout) { window.RedditTweaks.badgeTweak.updateColors(updated); } + if (settings.cardLayout) { + window.RedditTweaks.cardTweak.updateSettings(updated); + } }); }); } diff --git a/content/tweaks/badges.js b/content/tweaks/badges.js index e99b462..92e1c89 100644 --- a/content/tweaks/badges.js +++ b/content/tweaks/badges.js @@ -1,8 +1,6 @@ (function () { "use strict"; - let contentObserver = null; - let darkModeObserver = null; let currentSettings = null; function applyColorsToContainer(container, settings, subredditName) { @@ -93,52 +91,6 @@ }); } - function getObserverTarget() { - return ( - document.getElementById("siteTable") || - document.querySelector('.content[role="main"]') || - document.body - ); - } - - function startContentObserver(settings) { - if (contentObserver) contentObserver.disconnect(); - - const target = getObserverTarget(); - contentObserver = new MutationObserver(function (mutations) { - let hasNewPosts = false; - for (const mutation of mutations) { - for (const node of mutation.addedNodes) { - if (node.nodeType === Node.ELEMENT_NODE) { - if (node.matches && node.matches("div.thing.link")) { - hasNewPosts = true; - } else if (node.querySelector && node.querySelector("div.thing.link")) { - hasNewPosts = true; - } - } - } - } - if (hasNewPosts) processPosts(currentSettings); - }); - - contentObserver.observe(target, { childList: true, subtree: true }); - } - - function startDarkModeObserver() { - if (darkModeObserver) darkModeObserver.disconnect(); - - darkModeObserver = new MutationObserver(function () { - if (currentSettings && currentSettings.darkMode === "auto") { - updateColors(currentSettings); - } - }); - - darkModeObserver.observe(document.body, { - attributes: true, - attributeFilter: ["class"], - }); - } - function updateColors(settings) { currentSettings = settings; const containers = document.querySelectorAll(".reddit-tweaks-badges"); @@ -155,8 +107,6 @@ function apply(settings) { currentSettings = settings; processPosts(settings); - startContentObserver(settings); - startDarkModeObserver(); } window.RedditTweaks = window.RedditTweaks || {}; @@ -165,5 +115,6 @@ updateColors: updateColors, isDarkMode: window.RedditTweaks.isDarkMode, getColorPrefix: window.RedditTweaks.getColorPrefix, + processNewPosts: processPosts, }; })(); diff --git a/content/tweaks/cards.js b/content/tweaks/cards.js new file mode 100644 index 0000000..717b819 --- /dev/null +++ b/content/tweaks/cards.js @@ -0,0 +1,59 @@ +(function () { + "use strict"; + + function processPost(post) { + if (post.classList.contains("rt-card")) return; + post.classList.add("rt-card"); + } + + function processPosts() { + var posts = document.querySelectorAll("div.thing.link:not(.rt-card)"); + for (var i = 0; i < posts.length; i++) { + processPost(posts[i]); + } + } + + function applyDarkMode(settings) { + if (window.RedditTweaks.isDarkMode(settings)) { + document.documentElement.classList.add("rt-dark"); + } else { + document.documentElement.classList.remove("rt-dark"); + } + } + + function applyBackground(settings) { + if (settings.cardBackground === "shadcn") { + document.documentElement.classList.add("rt-card-bg-shadcn"); + } else { + document.documentElement.classList.remove("rt-card-bg-shadcn"); + } + } + + function applyGap(settings) { + var siteTable = document.getElementById("siteTable"); + if (siteTable) { + siteTable.style.setProperty("--rt-card-gap", settings.cardGap + "px"); + } + } + + function apply(settings) { + document.documentElement.classList.add("rt-card-enabled"); + applyDarkMode(settings); + applyBackground(settings); + applyGap(settings); + processPosts(); + } + + function updateSettings(settings) { + applyDarkMode(settings); + applyBackground(settings); + applyGap(settings); + } + + window.RedditTweaks = window.RedditTweaks || {}; + window.RedditTweaks.cardTweak = { + apply: apply, + updateSettings: updateSettings, + processNewPosts: processPosts, + }; +})(); diff --git a/manifest.json b/manifest.json index 767a1b6..44b93b0 100644 --- a/manifest.json +++ b/manifest.json @@ -15,13 +15,14 @@ }, "content_scripts": [ { - "matches": ["*://old.reddit.com/*", "*://www.reddit.com/*"], + "matches": ["*://old.reddit.com/*"], "css": ["content/styles/badges.css", "content/styles/cards.css"], "js": [ "lib/settings.js", "content/tweaks/badges.js", "content/tweaks/color-picker.js", "content/tweaks/color-popover.js", + "content/tweaks/cards.js", "content/main.js" ], "run_at": "document_idle"