mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 01:51:12 -05:00
Fix moderation queue tab switch reload
This commit is contained in:
@@ -157,13 +157,15 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
getAdminPanelPollInterval,
|
getAdminPanelPollInterval,
|
||||||
getAutoRefreshStrategy,
|
getAutoRefreshStrategy,
|
||||||
getPreserveInteractionState,
|
getPreserveInteractionState,
|
||||||
getUseRealtimeQueue
|
getUseRealtimeQueue,
|
||||||
|
getRefreshOnTabVisible
|
||||||
} = useAdminSettings();
|
} = useAdminSettings();
|
||||||
const refreshMode = getAdminPanelRefreshMode();
|
const refreshMode = getAdminPanelRefreshMode();
|
||||||
const pollInterval = getAdminPanelPollInterval();
|
const pollInterval = getAdminPanelPollInterval();
|
||||||
const refreshStrategy = getAutoRefreshStrategy();
|
const refreshStrategy = getAutoRefreshStrategy();
|
||||||
const preserveInteraction = getPreserveInteractionState();
|
const preserveInteraction = getPreserveInteractionState();
|
||||||
const useRealtimeQueue = getUseRealtimeQueue();
|
const useRealtimeQueue = getUseRealtimeQueue();
|
||||||
|
const refreshOnTabVisible = getRefreshOnTabVisible();
|
||||||
|
|
||||||
// Track recently removed items to prevent realtime override of optimistic updates
|
// Track recently removed items to prevent realtime override of optimistic updates
|
||||||
const recentlyRemovedRef = useRef<Set<string>>(new Set());
|
const recentlyRemovedRef = useRef<Set<string>>(new Set());
|
||||||
@@ -172,6 +174,8 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
// Store admin settings and stable refs to avoid triggering fetchItems recreation
|
// Store admin settings and stable refs to avoid triggering fetchItems recreation
|
||||||
const refreshStrategyRef = useRef(refreshStrategy);
|
const refreshStrategyRef = useRef(refreshStrategy);
|
||||||
const preserveInteractionRef = useRef(preserveInteraction);
|
const preserveInteractionRef = useRef(preserveInteraction);
|
||||||
|
const refreshOnTabVisibleRef = useRef(refreshOnTabVisible);
|
||||||
|
const activeTabRef = useRef<QueueTab>(activeTab);
|
||||||
const userRef = useRef(user);
|
const userRef = useRef(user);
|
||||||
const toastRef = useRef(toast);
|
const toastRef = useRef(toast);
|
||||||
const isAdminRef = useRef(isAdmin);
|
const isAdminRef = useRef(isAdmin);
|
||||||
@@ -180,11 +184,17 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
refreshStrategyRef.current = refreshStrategy;
|
refreshStrategyRef.current = refreshStrategy;
|
||||||
preserveInteractionRef.current = preserveInteraction;
|
preserveInteractionRef.current = preserveInteraction;
|
||||||
|
refreshOnTabVisibleRef.current = refreshOnTabVisible;
|
||||||
userRef.current = user;
|
userRef.current = user;
|
||||||
toastRef.current = toast;
|
toastRef.current = toast;
|
||||||
isAdminRef.current = isAdmin;
|
isAdminRef.current = isAdmin;
|
||||||
isSuperuserRef.current = isSuperuser;
|
isSuperuserRef.current = isSuperuser;
|
||||||
}, [refreshStrategy, preserveInteraction, user, toast, isAdmin, isSuperuser]);
|
}, [refreshStrategy, preserveInteraction, refreshOnTabVisible, user, toast, isAdmin, isSuperuser]);
|
||||||
|
|
||||||
|
// Sync activeTab with ref
|
||||||
|
useEffect(() => {
|
||||||
|
activeTabRef.current = activeTab;
|
||||||
|
}, [activeTab]);
|
||||||
|
|
||||||
// Persist sort configuration
|
// Persist sort configuration
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -1165,7 +1175,7 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
};
|
};
|
||||||
}, [user, useRealtimeQueue, debouncedRealtimeUpdate]);
|
}, [user, useRealtimeQueue, debouncedRealtimeUpdate]);
|
||||||
|
|
||||||
// Visibility change handler - pause queue updates when tab is hidden
|
// Visibility change handler - smart tab switching behavior
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleVisibilityChange = () => {
|
const handleVisibilityChange = () => {
|
||||||
if (document.hidden) {
|
if (document.hidden) {
|
||||||
@@ -1174,17 +1184,23 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
} else {
|
} else {
|
||||||
console.log('📱 Tab visible - resuming queue updates');
|
console.log('📱 Tab visible - resuming queue updates');
|
||||||
pauseFetchingRef.current = false;
|
pauseFetchingRef.current = false;
|
||||||
// Optional: trigger single refresh when tab becomes visible
|
|
||||||
if (initialFetchCompleteRef.current && !isMountingRef.current) {
|
// Check admin setting for auto-refresh behavior
|
||||||
console.log('🔄 Tab became visible - triggering refresh');
|
const shouldRefresh = refreshOnTabVisibleRef.current;
|
||||||
fetchItems(filtersRef.current.entityFilter, filtersRef.current.statusFilter, true, activeTab);
|
|
||||||
|
if (shouldRefresh && initialFetchCompleteRef.current && !isMountingRef.current) {
|
||||||
|
console.log('🔄 Tab became visible - triggering refresh (admin setting enabled)');
|
||||||
|
fetchItems(filtersRef.current.entityFilter, filtersRef.current.statusFilter, true, activeTabRef.current);
|
||||||
|
} else {
|
||||||
|
console.log('✅ Tab became visible - resuming without refresh');
|
||||||
|
// Realtime subscriptions will handle updates naturally
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||||
return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
|
return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||||
}, [fetchItems, activeTab]);
|
}, []); // Empty deps - all values come from refs
|
||||||
|
|
||||||
const handleResetToPending = async (item: ModerationItem) => {
|
const handleResetToPending = async (item: ModerationItem) => {
|
||||||
setActionLoading(item.id);
|
setActionLoading(item.id);
|
||||||
|
|||||||
@@ -157,6 +157,12 @@ export function useAdminSettings() {
|
|||||||
return cleanValue === 'true' || cleanValue === true;
|
return cleanValue === 'true' || cleanValue === true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getRefreshOnTabVisible = (): boolean => {
|
||||||
|
const value = getSettingValue('system.refresh_on_tab_visible', 'false');
|
||||||
|
const cleanValue = typeof value === 'string' ? value.replace(/"/g, '') : value;
|
||||||
|
return cleanValue === 'true' || cleanValue === true;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
settings,
|
settings,
|
||||||
isLoading,
|
isLoading,
|
||||||
@@ -180,5 +186,6 @@ export function useAdminSettings() {
|
|||||||
getAutoRefreshStrategy,
|
getAutoRefreshStrategy,
|
||||||
getPreserveInteractionState,
|
getPreserveInteractionState,
|
||||||
getUseRealtimeQueue,
|
getUseRealtimeQueue,
|
||||||
|
getRefreshOnTabVisible,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
-- Add admin setting to control auto-refresh on tab visibility change
|
||||||
|
INSERT INTO admin_settings (setting_key, setting_value, category, description, created_at, updated_at)
|
||||||
|
VALUES (
|
||||||
|
'system.refresh_on_tab_visible',
|
||||||
|
'false',
|
||||||
|
'system',
|
||||||
|
'Auto-refresh moderation queue when returning to tab (default: false, realtime handles updates)',
|
||||||
|
now(),
|
||||||
|
now()
|
||||||
|
)
|
||||||
|
ON CONFLICT (setting_key) DO NOTHING;
|
||||||
Reference in New Issue
Block a user