Keep tracker bar above comments and ignore screenshots
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ backend/data/*.db-wal
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
*.log
|
*.log
|
||||||
.env
|
.env
|
||||||
|
screenshots/
|
||||||
|
|||||||
@@ -242,6 +242,86 @@ function getTrackerInsertionAnchorInPost(postElement, buttonBar) {
|
|||||||
return anchor && anchor.parentElement === postElement ? anchor : null;
|
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 AI_CREDENTIAL_CACHE_TTL = 60 * 1000; // 1 minute cache
|
||||||
const aiCredentialCache = {
|
const aiCredentialCache = {
|
||||||
data: null,
|
data: null,
|
||||||
@@ -3790,29 +3870,35 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
inserted = tryInsertBeforeReelsCommentComposer();
|
inserted = tryInsertBeforeReelsCommentComposer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strategy 1: Insert right after the action block inside the current post container
|
const actionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
|
||||||
if (!inserted && buttonBar) {
|
const commentAnchor = findCommentSectionAnchorInPost(postElement, actionAnchor);
|
||||||
const actionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
|
|
||||||
if (actionAnchor && actionAnchor.parentElement) {
|
// Strategy 1: Insert before comment section so the bar stays above lazy-loaded comments
|
||||||
actionAnchor.parentElement.insertBefore(container, actionAnchor.nextSibling);
|
if (!inserted && commentAnchor && commentAnchor.parentElement) {
|
||||||
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after in-post action block. ID: #' + container.id);
|
commentAnchor.parentElement.insertBefore(container, commentAnchor);
|
||||||
inserted = true;
|
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)) {
|
if (!inserted && buttonBar && buttonBar.parentElement && postElement.contains(buttonBar.parentElement)) {
|
||||||
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
|
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
|
||||||
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after button bar (in-post fallback). ID: #' + container.id);
|
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after button bar (in-post fallback). ID: #' + container.id);
|
||||||
inserted = true;
|
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)) {
|
if (!inserted && buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement && !postElement.contains(buttonBar.parentElement.parentElement)) {
|
||||||
const grandParent = buttonBar.parentElement.parentElement;
|
const grandParent = buttonBar.parentElement.parentElement;
|
||||||
grandParent.insertBefore(container, buttonBar.parentElement.nextSibling);
|
grandParent.insertBefore(container, buttonBar.parentElement.nextSibling);
|
||||||
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after external button bar parent (legacy). ID: #' + container.id);
|
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after external button bar parent (legacy). ID: #' + container.id);
|
||||||
inserted = true;
|
inserted = true;
|
||||||
}
|
}
|
||||||
// Strategy 4: Append to post element
|
// Strategy 5: Append to post element
|
||||||
if (!inserted) {
|
if (!inserted) {
|
||||||
postElement.appendChild(container);
|
postElement.appendChild(container);
|
||||||
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted into article (fallback). ID: #' + container.id);
|
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...');
|
console.log('[FB Tracker] Post #' + postNum + ' - UI was removed, re-inserting...');
|
||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
// Try to re-insert
|
// Try to re-insert
|
||||||
const actionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
|
const currentActionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
|
||||||
if (actionAnchor && actionAnchor.parentElement) {
|
const currentCommentAnchor = findCommentSectionAnchorInPost(postElement, currentActionAnchor);
|
||||||
actionAnchor.parentElement.insertBefore(container, actionAnchor.nextSibling);
|
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)) {
|
} else if (buttonBar && buttonBar.parentElement && postElement.contains(buttonBar.parentElement)) {
|
||||||
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
|
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
|
||||||
} else if (buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement && !postElement.contains(buttonBar.parentElement.parentElement)) {
|
} else if (buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement && !postElement.contains(buttonBar.parentElement.parentElement)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user