Keep tracker bar above comments and ignore screenshots

This commit is contained in:
2026-02-26 00:06:35 +01:00
parent 12edc394b2
commit 233355319e
2 changed files with 105 additions and 15 deletions

3
.gitignore vendored
View File

@@ -4,4 +4,5 @@ backend/data/*.db-shm
backend/data/*.db-wal
.DS_Store
*.log
.env
.env
screenshots/

View File

@@ -242,6 +242,86 @@ function getTrackerInsertionAnchorInPost(postElement, buttonBar) {
return anchor && anchor.parentElement === postElement ? anchor : null;
}
function isNodeAfter(node, referenceNode) {
if (!node || !referenceNode || node === referenceNode) {
return false;
}
return Boolean(referenceNode.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_FOLLOWING);
}
function getTopLevelAnchorWithinPost(postElement, element) {
if (!postElement || !element || !postElement.contains(element)) {
return null;
}
let anchor = element;
while (anchor.parentElement && anchor.parentElement !== postElement) {
anchor = anchor.parentElement;
}
return anchor && anchor.parentElement === postElement ? anchor : null;
}
function findCommentSectionAnchorInPost(postElement, actionAnchor = null) {
if (!postElement) {
return null;
}
const selectors = [
'[aria-label*="relevantes zuerst" i]',
'[aria-label*="most relevant" i]',
'[aria-label*="neueste" i]',
'[aria-label*="newest" i]',
'[aria-label*="kommentare" i]',
'[aria-label*="comments" i]',
'[aria-roledescription*="kommentar" i]',
'[aria-roledescription*="comment" i]',
'[data-testid*="comment" i]',
'[data-scope="comment"]',
'div[role="textbox"][contenteditable="true"]',
'div[contenteditable="true"][data-lexical-editor="true"]',
'[aria-placeholder*="komment" i]',
'[aria-placeholder*="comment" i]'
];
const anchors = new Set();
postElement.querySelectorAll(selectors.join(', ')).forEach((candidate) => {
if (!candidate || candidate.closest('.fb-tracker-ui')) {
return;
}
let anchorSeed = candidate;
const isTextBox = candidate.matches('div[role="textbox"][contenteditable="true"], div[contenteditable="true"][data-lexical-editor="true"]');
if (isTextBox) {
anchorSeed = candidate.closest('form[role="presentation"]')
|| candidate.closest('form')
|| candidate;
}
const anchor = getTopLevelAnchorWithinPost(postElement, anchorSeed);
if (!anchor || anchor === actionAnchor) {
return;
}
if (actionAnchor && !isNodeAfter(anchor, actionAnchor)) {
return;
}
anchors.add(anchor);
});
if (!anchors.size) {
return null;
}
return Array.from(anchors).sort((a, b) => {
if (a === b) {
return 0;
}
return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
})[0];
}
const AI_CREDENTIAL_CACHE_TTL = 60 * 1000; // 1 minute cache
const aiCredentialCache = {
data: null,
@@ -3790,29 +3870,35 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
inserted = tryInsertBeforeReelsCommentComposer();
}
// Strategy 1: Insert right after the action block inside the current post container
if (!inserted && buttonBar) {
const actionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
if (actionAnchor && actionAnchor.parentElement) {
actionAnchor.parentElement.insertBefore(container, actionAnchor.nextSibling);
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after in-post action block. ID: #' + container.id);
inserted = true;
}
const actionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
const commentAnchor = findCommentSectionAnchorInPost(postElement, actionAnchor);
// Strategy 1: Insert before comment section so the bar stays above lazy-loaded comments
if (!inserted && commentAnchor && commentAnchor.parentElement) {
commentAnchor.parentElement.insertBefore(container, commentAnchor);
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted before comment section. ID: #' + container.id);
inserted = true;
}
// Strategy 2: Insert directly after the button bar if still inside the post container
// Strategy 2: Insert right after the action block inside the current post container
if (!inserted && actionAnchor && actionAnchor.parentElement) {
actionAnchor.parentElement.insertBefore(container, actionAnchor.nextSibling);
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after in-post action block. ID: #' + container.id);
inserted = true;
}
// Strategy 3: Insert directly after the button bar if still inside the post container
if (!inserted && buttonBar && buttonBar.parentElement && postElement.contains(buttonBar.parentElement)) {
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after button bar (in-post fallback). ID: #' + container.id);
inserted = true;
}
// Strategy 3: Legacy fallback for old variants where the interaction bar is outside the post container
// Strategy 4: Legacy fallback for old variants where the interaction bar is outside the post container
if (!inserted && buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement && !postElement.contains(buttonBar.parentElement.parentElement)) {
const grandParent = buttonBar.parentElement.parentElement;
grandParent.insertBefore(container, buttonBar.parentElement.nextSibling);
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after external button bar parent (legacy). ID: #' + container.id);
inserted = true;
}
// Strategy 4: Append to post element
// Strategy 5: Append to post element
if (!inserted) {
postElement.appendChild(container);
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted into article (fallback). ID: #' + container.id);
@@ -3843,9 +3929,12 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
console.log('[FB Tracker] Post #' + postNum + ' - UI was removed, re-inserting...');
observer.disconnect();
// Try to re-insert
const actionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
if (actionAnchor && actionAnchor.parentElement) {
actionAnchor.parentElement.insertBefore(container, actionAnchor.nextSibling);
const currentActionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
const currentCommentAnchor = findCommentSectionAnchorInPost(postElement, currentActionAnchor);
if (currentCommentAnchor && currentCommentAnchor.parentElement) {
currentCommentAnchor.parentElement.insertBefore(container, currentCommentAnchor);
} else if (currentActionAnchor && currentActionAnchor.parentElement) {
currentActionAnchor.parentElement.insertBefore(container, currentActionAnchor.nextSibling);
} else if (buttonBar && buttonBar.parentElement && postElement.contains(buttonBar.parentElement)) {
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
} else if (buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement && !postElement.contains(buttonBar.parentElement.parentElement)) {