Fix tracker bar placement and dedupe in new post layout
This commit is contained in:
@@ -189,6 +189,59 @@ function clearTrackerElementForPost(postElement, trackerElement = null) {
|
|||||||
trackerElementsByPost.delete(postElement);
|
trackerElementsByPost.delete(postElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTrackerScopeRoot(element) {
|
||||||
|
return element ? element.closest(DIALOG_ROOT_SELECTOR) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTrackersForUrlInScope(encodedUrl, scopeRoot) {
|
||||||
|
if (!encodedUrl) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const selector = `.fb-tracker-ui[data-post-url="${encodedUrl}"]`;
|
||||||
|
const trackers = Array.from(document.querySelectorAll(selector)).filter((tracker) => tracker && tracker.isConnected);
|
||||||
|
|
||||||
|
return trackers.filter((tracker) => {
|
||||||
|
const trackerScopeRoot = getTrackerScopeRoot(tracker);
|
||||||
|
if (scopeRoot) {
|
||||||
|
return trackerScopeRoot === scopeRoot;
|
||||||
|
}
|
||||||
|
return !trackerScopeRoot;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function dedupeTrackersForUrlInScope(encodedUrl, scopeRoot, preferredTracker = null) {
|
||||||
|
const trackers = getTrackersForUrlInScope(encodedUrl, scopeRoot);
|
||||||
|
if (!trackers.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keep = preferredTracker && trackers.includes(preferredTracker)
|
||||||
|
? preferredTracker
|
||||||
|
: trackers[trackers.length - 1];
|
||||||
|
|
||||||
|
trackers.forEach((tracker) => {
|
||||||
|
if (tracker !== keep) {
|
||||||
|
tracker.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return keep;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTrackerInsertionAnchorInPost(postElement, buttonBar) {
|
||||||
|
if (!postElement || !buttonBar || !postElement.contains(buttonBar)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let anchor = buttonBar;
|
||||||
|
while (anchor.parentElement && anchor.parentElement !== postElement) {
|
||||||
|
anchor = anchor.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return anchor && anchor.parentElement === postElement ? anchor : null;
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
@@ -3074,6 +3127,18 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
console.log('[FB Tracker] Post #' + postNum + ' - Creating tracker UI for:', postUrlData.url, postElement);
|
console.log('[FB Tracker] Post #' + postNum + ' - Creating tracker UI for:', postUrlData.url, postElement);
|
||||||
|
|
||||||
const encodedUrl = encodeURIComponent(postUrlData.url);
|
const encodedUrl = encodeURIComponent(postUrlData.url);
|
||||||
|
const scopeRoot = getTrackerScopeRoot(postElement);
|
||||||
|
|
||||||
|
const existingScopedTrackers = getTrackersForUrlInScope(encodedUrl, scopeRoot);
|
||||||
|
if (existingScopedTrackers.length > 0) {
|
||||||
|
const scopedTracker = dedupeTrackersForUrlInScope(encodedUrl, scopeRoot, existingScopedTrackers[0]);
|
||||||
|
if (scopedTracker) {
|
||||||
|
console.log('[FB Tracker] Post #' + postNum + ' - Reusing existing tracker UI in same scope');
|
||||||
|
setTrackerElementForPost(postElement, scopedTracker);
|
||||||
|
postElement.setAttribute(PROCESSED_ATTR, '1');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const existingEntry = processedPostUrls.get(encodedUrl);
|
const existingEntry = processedPostUrls.get(encodedUrl);
|
||||||
if (existingEntry && existingEntry.element && existingEntry.element !== postElement) {
|
if (existingEntry && existingEntry.element && existingEntry.element !== postElement) {
|
||||||
@@ -3083,10 +3148,7 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
} else {
|
} else {
|
||||||
processedPostUrls.delete(encodedUrl);
|
processedPostUrls.delete(encodedUrl);
|
||||||
}
|
}
|
||||||
const otherUI = document.querySelector(`.fb-tracker-ui[data-post-url="${encodedUrl}"]`);
|
getTrackersForUrlInScope(encodedUrl, scopeRoot).forEach((tracker) => tracker.remove());
|
||||||
if (otherUI) {
|
|
||||||
otherUI.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { likeButton: sourceLikeButton = null, isSearchResult = false, isDialogContext = false } = options;
|
const { likeButton: sourceLikeButton = null, isSearchResult = false, isDialogContext = false } = options;
|
||||||
@@ -3114,6 +3176,8 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
row-gap: 6px;
|
row-gap: 6px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
`;
|
`;
|
||||||
@@ -3726,20 +3790,29 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
inserted = tryInsertBeforeReelsCommentComposer();
|
inserted = tryInsertBeforeReelsCommentComposer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strategy 1: After button bar's parent (more stable)
|
// Strategy 1: Insert right after the action block inside the current post container
|
||||||
if (!inserted && buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement) {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Strategy 2: 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
|
||||||
|
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 button bar parent. 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 2: After button bar directly
|
// Strategy 4: Append to post element
|
||||||
if (!inserted && buttonBar && buttonBar.parentElement) {
|
|
||||||
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
|
|
||||||
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted after button bar. ID: #' + container.id);
|
|
||||||
inserted = true;
|
|
||||||
}
|
|
||||||
// Strategy 3: 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);
|
||||||
@@ -3747,6 +3820,11 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (inserted) {
|
if (inserted) {
|
||||||
|
const dedupedTracker = dedupeTrackersForUrlInScope(encodedUrl, scopeRoot, container);
|
||||||
|
if (dedupedTracker && dedupedTracker !== container) {
|
||||||
|
clearTrackerElementForPost(postElement, container);
|
||||||
|
}
|
||||||
|
|
||||||
processedPostUrls.set(encodedUrl, {
|
processedPostUrls.set(encodedUrl, {
|
||||||
element: postElement,
|
element: postElement,
|
||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
@@ -3755,7 +3833,7 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
: null,
|
: null,
|
||||||
hidden: false
|
hidden: false
|
||||||
});
|
});
|
||||||
setTrackerElementForPost(postElement, container);
|
setTrackerElementForPost(postElement, dedupedTracker || container);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monitor if the UI gets removed and re-insert it
|
// Monitor if the UI gets removed and re-insert it
|
||||||
@@ -3765,12 +3843,18 @@ 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
|
||||||
if (buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement) {
|
const actionAnchor = getTrackerInsertionAnchorInPost(postElement, buttonBar);
|
||||||
|
if (actionAnchor && actionAnchor.parentElement) {
|
||||||
|
actionAnchor.parentElement.insertBefore(container, actionAnchor.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)) {
|
||||||
buttonBar.parentElement.parentElement.insertBefore(container, buttonBar.parentElement.nextSibling);
|
buttonBar.parentElement.parentElement.insertBefore(container, buttonBar.parentElement.nextSibling);
|
||||||
} else if (postElement.parentElement) {
|
} else if (postElement) {
|
||||||
postElement.parentElement.appendChild(container);
|
postElement.appendChild(container);
|
||||||
}
|
}
|
||||||
if (container.isConnected) {
|
if (container.isConnected) {
|
||||||
|
dedupeTrackersForUrlInScope(encodedUrl, scopeRoot, container);
|
||||||
setTrackerElementForPost(postElement, container);
|
setTrackerElementForPost(postElement, container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user