diff --git a/extension/content.js b/extension/content.js index 1ec7b70..5c03c60 100644 --- a/extension/content.js +++ b/extension/content.js @@ -19,6 +19,17 @@ const sessionSearchInfoCache = new Map(); const trackerElementsByPost = new WeakMap(); +const REELS_PATH_PREFIX = '/reel/'; + +function isOnReelsPage() { + try { + const pathname = window.location && window.location.pathname; + return typeof pathname === 'string' && pathname.startsWith(REELS_PATH_PREFIX); + } catch (error) { + return false; + } +} + function getTrackerElementForPost(postElement) { if (!postElement) { return null; @@ -744,6 +755,7 @@ function hidePostElement(postElement) { return; } const removalSelectors = [ + 'div[role="complementary"]', '[role="listitem"][aria-posinset]', 'div[aria-posinset]', 'div[data-ad-comet-feed-verbose-tracking]', @@ -1074,6 +1086,10 @@ function findPostContainers() { 'div[data-pagelet*="QPE_PublisherStory"]' ]; + if (isOnReelsPage()) { + candidateSelectors.push('div[role="complementary"]'); + } + const candidateElements = document.querySelectorAll(candidateSelectors.join(', ')); candidateElements.forEach((element) => { @@ -1094,7 +1110,7 @@ function findPostContainers() { const likeButton = findLikeButtonWithin(container); seen.add(container); - if (likeButton) { + if (likeButton || isOnReelsPage()) { containers.push({ container, likeButton, buttonBar: buttonBar || null }); } }); @@ -2248,6 +2264,12 @@ function isMainPost(article, buttonBar) { return false; } + if (isOnReelsPage()) { + if (article.matches('div[role="complementary"]') || article.closest('div[role="complementary"]')) { + return true; + } + } + const roleDescription = (article.getAttribute('aria-roledescription') || '').toLowerCase(); if (roleDescription && (roleDescription.includes('kommentar') || roleDescription.includes('comment'))) { return false; @@ -2490,7 +2512,10 @@ const visibilityObserver = new IntersectionObserver((entries) => { // Watch for new posts and observe them const postObserver = new MutationObserver((mutations) => { // Find all posts and observe them for visibility - const posts = document.querySelectorAll('div[aria-posinset]'); + const postSelector = isOnReelsPage() + ? 'div[aria-posinset], div[role="complementary"]' + : 'div[aria-posinset]'; + const posts = document.querySelectorAll(postSelector); posts.forEach(post => { if (!post.dataset.trackerObserved) { post.dataset.trackerObserved = 'true'; @@ -2508,7 +2533,10 @@ postObserver.observe(document.body, { }); // Initial observation of existing posts -const initialPosts = document.querySelectorAll('div[aria-posinset]'); +const initialPostSelector = isOnReelsPage() + ? 'div[aria-posinset], div[role="complementary"]' + : 'div[aria-posinset]'; +const initialPosts = document.querySelectorAll(initialPostSelector); initialPosts.forEach(post => { post.dataset.trackerObserved = 'true'; visibilityObserver.observe(post); @@ -2544,6 +2572,9 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { // Find the post container (aria-posinset) let postContainer = clickedElement.closest('div[aria-posinset]'); + if (!postContainer && isOnReelsPage()) { + postContainer = clickedElement.closest('div[role="complementary"]'); + } if (!postContainer) { console.log('[FB Tracker] No post container found for clicked element:', clickedElement); @@ -2692,6 +2723,10 @@ function ensurePrimaryPostElement(element) { 'article' ]; + if (isOnReelsPage()) { + selectors.unshift('div[role="complementary"]'); + } + let current = element; while (current && current !== document.body && current !== document.documentElement) { for (const selector of selectors) { @@ -3024,7 +3059,7 @@ async function waitForCommentInput(postElement, options = {}) { continue; } - const trackerContainer = tracker.closest('div[aria-posinset], article[role="article"], article'); + const trackerContainer = tracker.closest('div[aria-posinset], article[role="article"], article, div[role="complementary"]'); if (trackerContainer) { const input = findCommentInput(trackerContainer, { preferredRoot }); if (isElementVisible(input)) { @@ -3374,7 +3409,7 @@ async function addAICommentButton(container, postElement) { }); button.addEventListener('pointerdown', () => { - const contextElement = container.closest('div[aria-posinset], article[role="article"], article'); + const contextElement = container.closest('div[aria-posinset], article[role="article"], article, div[role="complementary"]'); const normalized = contextElement ? ensurePrimaryPostElement(contextElement) : null; const fallbackNormalized = postElement ? ensurePrimaryPostElement(postElement) : null; const target = normalized || fallbackNormalized || contextElement || postElement || container; @@ -3612,7 +3647,7 @@ async function addAICommentButton(container, postElement) { button.textContent = '⏳ Generiere...'; try { - const contextCandidate = container.closest('div[aria-posinset], article[role="article"], article'); + const contextCandidate = container.closest('div[aria-posinset], article[role="article"], article, div[role="complementary"]'); const normalizedContext = contextCandidate ? ensurePrimaryPostElement(contextCandidate) : null; const fallbackContext = postElement ? ensurePrimaryPostElement(postElement) : null; const postContext = normalizedContext || fallbackContext || contextCandidate || postElement || container;