Add AI button reactivation countdown
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// Facebook Post Tracker Extension
|
||||
// Uses API_BASE_URL from config.js
|
||||
|
||||
const EXTENSION_VERSION = '1.2.1';
|
||||
const EXTENSION_VERSION = '1.2.2';
|
||||
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"]';
|
||||
@@ -1019,6 +1019,7 @@ const aiCredentialCache = {
|
||||
const AI_SETTINGS_CACHE_TTL = 30 * 1000;
|
||||
const AI_SETTINGS_SYNC_KEY = 'fb_tracker_ai_settings_sync';
|
||||
const AI_AVAILABILITY_AUTO_REFRESH_INTERVAL_MS = 30 * 1000;
|
||||
const AI_REACTIVATION_COUNTDOWN_THRESHOLD_MS = 5 * 60 * 1000;
|
||||
const aiSettingsCache = {
|
||||
data: null,
|
||||
timestamp: 0,
|
||||
@@ -6852,6 +6853,7 @@ async function addAICommentButton(container, postElement) {
|
||||
let notePreviewElement = null;
|
||||
let noteClearButton = null;
|
||||
let rateLimitRefreshPromise = null;
|
||||
let blockedCountdownIntervalId = null;
|
||||
|
||||
const truncateNoteForPreview = (note) => {
|
||||
if (!note) {
|
||||
@@ -6887,6 +6889,81 @@ async function addAICommentButton(container, postElement) {
|
||||
showToast(`⏳ ${status.profile_name || 'Profil'}: ${formatAIAutoCommentRateLimitReason(status)}.${untilText}`.trim(), 'info');
|
||||
};
|
||||
|
||||
const clearBlockedCountdown = () => {
|
||||
if (blockedCountdownIntervalId) {
|
||||
window.clearInterval(blockedCountdownIntervalId);
|
||||
blockedCountdownIntervalId = null;
|
||||
}
|
||||
};
|
||||
|
||||
const getBlockedCountdownRemainingMs = (status) => {
|
||||
if (!status || !status.blocked_until) {
|
||||
return null;
|
||||
}
|
||||
const blockedUntilMs = new Date(status.blocked_until).getTime();
|
||||
if (!Number.isFinite(blockedUntilMs)) {
|
||||
return null;
|
||||
}
|
||||
return blockedUntilMs - Date.now();
|
||||
};
|
||||
|
||||
const formatBlockedCountdown = (remainingMs) => {
|
||||
const totalSeconds = Math.max(0, Math.ceil(remainingMs / 1000));
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
||||
const seconds = totalSeconds % 60;
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
||||
}
|
||||
return `${minutes}:${String(seconds).padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const renderBlockedCountdownText = (status) => {
|
||||
const remainingMs = getBlockedCountdownRemainingMs(status);
|
||||
if (remainingMs === null || remainingMs <= 0 || remainingMs > AI_REACTIVATION_COUNTDOWN_THRESHOLD_MS) {
|
||||
return false;
|
||||
}
|
||||
button.textContent = `${button.dataset.aiOriginalText || baseButtonText} 🔒 ${formatBlockedCountdown(remainingMs)}`;
|
||||
return true;
|
||||
};
|
||||
|
||||
const scheduleBlockedCountdown = (status) => {
|
||||
clearBlockedCountdown();
|
||||
if (!status || !status.blocked) {
|
||||
return;
|
||||
}
|
||||
if ((button.dataset.aiState || 'idle') !== 'idle' || button._aiContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updateCountdown = () => {
|
||||
if (!wrapper.isConnected) {
|
||||
clearBlockedCountdown();
|
||||
return;
|
||||
}
|
||||
if ((button.dataset.aiState || 'idle') !== 'idle' || button._aiContext) {
|
||||
clearBlockedCountdown();
|
||||
return;
|
||||
}
|
||||
const remainingMs = getBlockedCountdownRemainingMs(status);
|
||||
if (remainingMs !== null && remainingMs <= 0) {
|
||||
clearBlockedCountdown();
|
||||
void refreshAvailabilityState(true);
|
||||
return;
|
||||
}
|
||||
if (!renderBlockedCountdownText(status)) {
|
||||
clearBlockedCountdown();
|
||||
}
|
||||
};
|
||||
|
||||
if (!renderBlockedCountdownText(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
blockedCountdownIntervalId = window.setInterval(updateCountdown, 1000);
|
||||
};
|
||||
|
||||
const applyAvailabilityState = (status = null, options = {}) => {
|
||||
const { preserveText = false } = options;
|
||||
const blocked = Boolean(status && status.blocked);
|
||||
@@ -6894,6 +6971,7 @@ async function addAICommentButton(container, postElement) {
|
||||
button.dataset.aiAvailability = blocked ? 'blocked' : 'available';
|
||||
|
||||
if (blocked) {
|
||||
clearBlockedCountdown();
|
||||
wrapper.style.opacity = '0.72';
|
||||
wrapper.style.boxShadow = baseWrapperShadow;
|
||||
wrapper.style.transform = 'translateY(0)';
|
||||
@@ -6904,10 +6982,15 @@ async function addAICommentButton(container, postElement) {
|
||||
button.title = buildBlockedButtonTitle(status);
|
||||
dropdownButton.title = buildBlockedButtonTitle(status);
|
||||
dropdownButton.setAttribute('aria-label', buildBlockedButtonTitle(status));
|
||||
if (!preserveText && (button.dataset.aiState || 'idle') === 'idle' && !button._aiContext) {
|
||||
button.textContent = `${button.dataset.aiOriginalText || baseButtonText} 🔒`;
|
||||
if ((button.dataset.aiState || 'idle') === 'idle' && !button._aiContext) {
|
||||
const countdownVisible = renderBlockedCountdownText(status);
|
||||
if (!countdownVisible && !preserveText) {
|
||||
button.textContent = `${button.dataset.aiOriginalText || baseButtonText} 🔒`;
|
||||
}
|
||||
scheduleBlockedCountdown(status);
|
||||
}
|
||||
} else {
|
||||
clearBlockedCountdown();
|
||||
wrapper.style.opacity = '1';
|
||||
wrapper.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
|
||||
button.style.cursor = 'pointer';
|
||||
@@ -6959,6 +7042,7 @@ async function addAICommentButton(container, postElement) {
|
||||
|
||||
const handleSharedAISettingsUpdate = async (settings) => {
|
||||
if (!wrapper.isConnected) {
|
||||
clearBlockedCountdown();
|
||||
aiAvailabilitySubscribers.delete(handleSharedAISettingsUpdate);
|
||||
return;
|
||||
}
|
||||
@@ -6980,6 +7064,7 @@ async function addAICommentButton(container, postElement) {
|
||||
|
||||
const handleAutoRefreshAvailability = ({ forceRefresh = false } = {}) => {
|
||||
if (!wrapper.isConnected) {
|
||||
clearBlockedCountdown();
|
||||
aiAvailabilitySubscribers.delete(handleSharedAISettingsUpdate);
|
||||
aiAvailabilityRefreshSubscribers.delete(handleAutoRefreshAvailability);
|
||||
return;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Facebook Post Tracker",
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.2",
|
||||
"description": "Track Facebook posts across multiple profiles",
|
||||
"permissions": [
|
||||
"storage",
|
||||
|
||||
Reference in New Issue
Block a user