Harden tracker anchor detection for new comment layout
This commit is contained in:
@@ -309,17 +309,94 @@ function getTrackerInsertionAnchorInPost(postElement, buttonBar) {
|
||||
return anchor && anchor.parentElement === postElement ? anchor : null;
|
||||
}
|
||||
|
||||
function hasCommentComposerSignal(node) {
|
||||
if (!node || !node.querySelector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Boolean(
|
||||
node.querySelector(
|
||||
'div[role="textbox"][contenteditable="true"], [role="textbox"][aria-label*="komment" i], [role="textbox"][aria-label*="comment" i], [role="textbox"][aria-placeholder*="komment" i], [role="textbox"][aria-placeholder*="comment" i]'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function countActionRoleSignals(node) {
|
||||
if (!node || !node.querySelector) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const hasLike = Boolean(node.querySelector('[data-ad-rendering-role="like_button"], [data-ad-rendering-role*="gefällt" i]'));
|
||||
const hasComment = Boolean(node.querySelector('[data-ad-rendering-role="comment_button"]'));
|
||||
const hasShare = Boolean(node.querySelector('[data-ad-rendering-role="share_button"]'));
|
||||
|
||||
return [hasLike, hasComment, hasShare].filter(Boolean).length;
|
||||
}
|
||||
|
||||
function isReliableActionBarCandidate(postElement, candidate) {
|
||||
if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (candidate.closest('.fb-tracker-ui')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasCommentComposerSignal(candidate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const buttonCount = candidate.querySelectorAll('[role="button"], button').length;
|
||||
if (buttonCount > 80) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const actionRoleSignals = countActionRoleSignals(candidate);
|
||||
if (actionRoleSignals >= 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return hasInteractionButtons(candidate);
|
||||
}
|
||||
|
||||
function findActionBarByDataRoles(postElement) {
|
||||
if (!postElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const markers = Array.from(postElement.querySelectorAll(
|
||||
'[data-ad-rendering-role="like_button"], [data-ad-rendering-role*="gefällt" i], [data-ad-rendering-role="comment_button"], [data-ad-rendering-role="share_button"]'
|
||||
));
|
||||
|
||||
for (const marker of markers) {
|
||||
let current = marker;
|
||||
for (let depth = 0; depth < 8 && current && current !== postElement; depth++) {
|
||||
if (isReliableActionBarCandidate(postElement, current)) {
|
||||
return current;
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolveActionButtonBar(postElement, buttonBar) {
|
||||
if (!postElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (buttonBar && buttonBar.isConnected && postElement.contains(buttonBar)) {
|
||||
const dataRoleResolved = findActionBarByDataRoles(postElement);
|
||||
if (dataRoleResolved) {
|
||||
return dataRoleResolved;
|
||||
}
|
||||
|
||||
if (buttonBar && isReliableActionBarCandidate(postElement, buttonBar)) {
|
||||
return buttonBar;
|
||||
}
|
||||
|
||||
const resolved = findButtonBar(postElement);
|
||||
if (resolved && resolved.isConnected && postElement.contains(resolved)) {
|
||||
if (resolved && isReliableActionBarCandidate(postElement, resolved)) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
@@ -428,6 +505,29 @@ function findAdjacentCommentSortAnchor(postElement, actionAnchor = null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function findCommentSortAnchorInPost(postElement) {
|
||||
if (!postElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sortCandidates = Array.from(
|
||||
postElement.querySelectorAll('[aria-label*="relevantes zuerst" i], [aria-label*="most relevant" i], [aria-label*="neueste" i], [aria-label*="newest" i], [role="button"], button')
|
||||
);
|
||||
|
||||
for (const candidate of sortCandidates) {
|
||||
if (!isLikelyCommentSortNode(candidate)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const topLevel = getTopLevelAnchorWithinPost(postElement, candidate) || candidate;
|
||||
if (topLevel && topLevel.parentElement && postElement.contains(topLevel)) {
|
||||
return topLevel;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function createTrackerInsertionMarker() {
|
||||
const marker = document.createElement('div');
|
||||
marker.className = 'fb-tracker-insertion-anchor';
|
||||
@@ -472,6 +572,14 @@ function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum
|
||||
return true;
|
||||
}
|
||||
|
||||
const fallbackSortAnchor = findCommentSortAnchorInPost(postElement);
|
||||
if (fallbackSortAnchor && fallbackSortAnchor.parentElement) {
|
||||
fallbackSortAnchor.parentElement.insertBefore(marker, fallbackSortAnchor);
|
||||
setTrackerInsertionMarkerLocked(marker, true);
|
||||
console.log('[FB Tracker] Post #' + postNum + ' - Marker fallback inserted before comment sort');
|
||||
return true;
|
||||
}
|
||||
|
||||
postElement.appendChild(marker);
|
||||
setTrackerInsertionMarkerLocked(marker, false);
|
||||
console.log('[FB Tracker] Post #' + postNum + ' - Marker fallback appended to post');
|
||||
|
||||
Reference in New Issue
Block a user