From 8c5cef90fa4a2dfd6c1c77344b465ad3ba237f14 Mon Sep 17 00:00:00 2001 From: Meik Date: Thu, 26 Feb 2026 09:03:17 +0100 Subject: [PATCH] Anchor tracker before feedback section to avoid FB action row overlap --- extension/content.js | 80 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/extension/content.js b/extension/content.js index e6ee4e8..cc2e1e4 100644 --- a/extension/content.js +++ b/extension/content.js @@ -418,6 +418,18 @@ function isCompactActionBarCandidate(postElement, candidate) { return hasInteractionButtons(candidate); } +function hasMainPostContentSignal(node) { + if (!node || !node.querySelector) { + return false; + } + + return Boolean( + node.querySelector( + '[data-ad-preview*="message" i], [data-ad-comet-preview*="message" i], [data-ad-preview*="story" i], [data-ad-comet-preview*="story" i]' + ) + ); +} + function normalizeActionBarCandidate(postElement, candidate) { if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) { return null; @@ -444,6 +456,55 @@ function normalizeActionBarCandidate(postElement, candidate) { return isReliableActionBarCandidate(postElement, candidate) ? candidate : null; } +function findFeedbackSectionAnchor(postElement, actionAnchor = null) { + if (!postElement) { + return null; + } + + const resolvedAction = actionAnchor && postElement.contains(actionAnchor) + ? actionAnchor + : resolveActionButtonBar(postElement, actionAnchor); + if (!resolvedAction || !resolvedAction.isConnected || !postElement.contains(resolvedAction)) { + return null; + } + + const commentBoundary = findCommentBoundaryAnchorInPost(postElement, resolvedAction); + let candidate = resolvedAction; + let current = resolvedAction; + + for (let depth = 0; depth < 12 && current && current !== postElement; depth++) { + const parent = current.parentElement; + if (!parent || !postElement.contains(parent) || parent === postElement) { + break; + } + + if (hasMainPostContentSignal(parent)) { + break; + } + + const parentLooksFeedback = + (commentBoundary && parent.contains(commentBoundary)) + || hasCommentComposerSignal(parent) + || hasCommentSortSignal(parent) + || hasCommentContentSignal(parent); + + if (!parentLooksFeedback) { + // Keep climbing through transparent wrappers that only wrap this subtree. + if (parent.childElementCount === 1) { + candidate = parent; + current = parent; + continue; + } + break; + } + + candidate = parent; + current = parent; + } + + return candidate; +} + function isReliableActionBarCandidate(postElement, candidate) { if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) { return false; @@ -772,6 +833,13 @@ function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum const resolvedButtonBar = resolveActionButtonBar(postElement, buttonBar); const actionAnchor = getDirectActionAnchorInPost(postElement, resolvedButtonBar); + const feedbackAnchor = findFeedbackSectionAnchor(postElement, actionAnchor || resolvedButtonBar); + + if (feedbackAnchor && insertMarkerBeforeAnchor(postElement, marker, feedbackAnchor)) { + setTrackerInsertionMarkerLocked(marker, true); + console.log('[FB Tracker] Post #' + postNum + ' - Marker inserted above feedback section'); + return true; + } if (actionAnchor && insertMarkerBeforeAnchor(postElement, marker, actionAnchor)) { setTrackerInsertionMarkerLocked(marker, true); @@ -805,6 +873,18 @@ function isTrackerInsertionMarkerPlacementValid(postElement, marker, buttonBar) } const actionAnchor = getDirectActionAnchorInPost(postElement, buttonBar); + const feedbackAnchor = findFeedbackSectionAnchor(postElement, actionAnchor || buttonBar); + if (feedbackAnchor && isNodeAfter(marker, feedbackAnchor)) { + return false; + } + + if (feedbackAnchor && marker.parentElement === feedbackAnchor.parentElement) { + const nextSibling = getNextNonTrackerSibling(marker); + if (nextSibling && nextSibling !== feedbackAnchor) { + return false; + } + } + if (actionAnchor) { if (isNodeAfter(marker, actionAnchor)) { return false;