diff --git a/extension/content.js b/extension/content.js index 6e268bf..0e4ac41 100644 --- a/extension/content.js +++ b/extension/content.js @@ -1,7 +1,7 @@ // Facebook Post Tracker Extension // Uses API_BASE_URL from config.js -const EXTENSION_VERSION = '1.2.3'; +const EXTENSION_VERSION = '1.2.4'; const PROCESSED_ATTR = 'data-fb-tracker-processed'; const PENDING_ATTR = 'data-fb-tracker-pending'; const DIALOG_ROOT_SELECTOR = '[role="dialog"], [data-pagelet*="Modal"], [data-pagelet="StoriesRecentStoriesFeedSection"]'; @@ -18,6 +18,7 @@ const FEED_HOME_PATHS = ['/', '/home.php']; const sessionSearchRecordedUrls = new Set(); const sessionSearchInfoCache = new Map(); let profileSelectionNoticeShown = false; +let extensionPaused = false; function isOnSearchResultsPage() { try { @@ -132,16 +133,57 @@ function applyDebugLoggingPreference(value) { } } -chrome.storage.sync.get(['debugLoggingEnabled'], (result) => { +function resetTrackerUiState() { + document.querySelectorAll('.fb-tracker-ui').forEach((element) => { + const host = getTrackerHostElement(element); + if (host) { + host.removeAttribute(PROCESSED_ATTR); + host.removeAttribute(PENDING_ATTR); + clearTrackerElementForPost(host, element); + } + element.remove(); + }); + + document.querySelectorAll(`[${PROCESSED_ATTR}], [${PENDING_ATTR}]`).forEach((element) => { + element.removeAttribute(PROCESSED_ATTR); + element.removeAttribute(PENDING_ATTR); + }); + + processedPostUrls.clear(); +} + +function applyExtensionPausedPreference(value) { + extensionPaused = Boolean(value); + if (extensionPaused) { + hideSelectionAIButton(); + resetTrackerUiState(); + originalConsoleLog('[FB Tracker] Extension paused'); + return; + } + + originalConsoleLog('[FB Tracker] Extension resumed'); + scheduleScan(); +} + +chrome.storage.sync.get(['debugLoggingEnabled', 'extensionPaused'], (result) => { applyDebugLoggingPreference(result && typeof result.debugLoggingEnabled !== 'undefined' ? result.debugLoggingEnabled : false); + applyExtensionPausedPreference(result && typeof result.extensionPaused !== 'undefined' + ? result.extensionPaused + : false); }); chrome.storage.onChanged.addListener((changes, area) => { - if (area === 'sync' && changes && Object.prototype.hasOwnProperty.call(changes, 'debugLoggingEnabled')) { + if (area !== 'sync' || !changes) { + return; + } + if (Object.prototype.hasOwnProperty.call(changes, 'debugLoggingEnabled')) { applyDebugLoggingPreference(changes.debugLoggingEnabled.newValue); } + if (Object.prototype.hasOwnProperty.call(changes, 'extensionPaused')) { + applyExtensionPausedPreference(changes.extensionPaused.newValue); + } }); function getTrackerElementForPost(postElement) { @@ -4119,6 +4161,10 @@ async function renderTrackedStatus({ // Create the tracking UI async function createTrackerUI(postElement, buttonBar, postNum = '?', options = {}) { + if (extensionPaused) { + return; + } + // Normalize to top-level post container if nested element passed postElement = ensurePrimaryPostElement(postElement); @@ -4972,6 +5018,10 @@ let globalPostCounter = 0; // Find all Facebook posts on the page function findPosts() { + if (extensionPaused) { + return; + } + if (maybeRedirectPageReelsToMain()) { return; } @@ -5100,6 +5150,9 @@ setTimeout(findPosts, 6000); // Debounced scan function let scanTimeout = null; function scheduleScan() { + if (extensionPaused) { + return; + } if (scanTimeout) { clearTimeout(scanTimeout); } @@ -5405,6 +5458,11 @@ const positionSelectionAIButton = (rect) => { const updateSelectionAIButton = async () => { clearSelectionAIHideTimeout(); + if (extensionPaused) { + hideSelectionAIButton(); + return; + } + if (selectionAIEnabledCached === null) { try { selectionAIEnabledCached = await isAIEnabled(); @@ -5498,6 +5556,11 @@ initSelectionAIFloatingButton(); // Listen for manual reparse command chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (extensionPaused && message && (message.type === 'generateSelectionAI' || message.type === 'reparsePost')) { + sendResponse({ success: false, paused: true }); + return true; + } + if (message && message.type === 'generateSelectionAI') { handleSelectionAIRequest(message.selectionText || '', sendResponse); return true; diff --git a/extension/manifest.json b/extension/manifest.json index 4b292d6..8f95efa 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Facebook Post Tracker", - "version": "1.2.3", + "version": "1.2.4", "description": "Track Facebook posts across multiple profiles", "permissions": [ "storage", diff --git a/extension/popup.html b/extension/popup.html index 687ea6c..5bc5532 100644 --- a/extension/popup.html +++ b/extension/popup.html @@ -137,6 +137,10 @@ +