mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-17 00:06:30 +00:00
115 lines
No EOL
3.5 KiB
TypeScript
115 lines
No EOL
3.5 KiB
TypeScript
import { useState, useCallback, useRef, useEffect } from 'react';
|
|
import { CatalogContent, catalogService } from '../services/catalogService';
|
|
import { logger } from '../utils/logger';
|
|
import { useCatalogContext } from '../contexts/CatalogContext';
|
|
import { addonEmitter, ADDON_EVENTS } from '../services/stremioService';
|
|
|
|
export function useHomeCatalogs() {
|
|
const [catalogs, setCatalogs] = useState<CatalogContent[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [refreshing, setRefreshing] = useState(false);
|
|
const abortControllerRef = useRef<AbortController | null>(null);
|
|
const { lastUpdate } = useCatalogContext();
|
|
|
|
const cleanup = useCallback(() => {
|
|
if (abortControllerRef.current) {
|
|
abortControllerRef.current.abort();
|
|
abortControllerRef.current = null;
|
|
}
|
|
}, []);
|
|
|
|
const loadCatalogs = useCallback(async (isRefresh = false) => {
|
|
if (!isRefresh) {
|
|
setLoading(true);
|
|
} else {
|
|
setRefreshing(true);
|
|
}
|
|
|
|
cleanup();
|
|
abortControllerRef.current = new AbortController();
|
|
const signal = abortControllerRef.current.signal;
|
|
|
|
try {
|
|
const homeCatalogs = await catalogService.getHomeCatalogs();
|
|
|
|
if (signal.aborted) return;
|
|
|
|
if (!homeCatalogs?.length) {
|
|
logger.warn('No home catalogs found.');
|
|
setCatalogs([]); // Ensure catalogs is empty if none found
|
|
return;
|
|
}
|
|
|
|
const uniqueCatalogsMap = new Map();
|
|
homeCatalogs.forEach(catalog => {
|
|
const contentKey = catalog.items.map(item => item.id).sort().join(',');
|
|
if (!uniqueCatalogsMap.has(contentKey)) {
|
|
uniqueCatalogsMap.set(contentKey, catalog);
|
|
}
|
|
});
|
|
|
|
if (signal.aborted) return;
|
|
|
|
const uniqueCatalogs = Array.from(uniqueCatalogsMap.values());
|
|
setCatalogs(uniqueCatalogs);
|
|
|
|
} catch (error) {
|
|
if (signal.aborted) {
|
|
logger.info('Catalog fetch aborted');
|
|
} else {
|
|
logger.error('Error in loadCatalogs:', error);
|
|
}
|
|
setCatalogs([]); // Clear catalogs on error
|
|
} finally {
|
|
if (!signal.aborted) {
|
|
setLoading(false);
|
|
setRefreshing(false);
|
|
}
|
|
}
|
|
}, [cleanup]);
|
|
|
|
// Initial load and reload on lastUpdate change
|
|
useEffect(() => {
|
|
loadCatalogs();
|
|
}, [loadCatalogs, lastUpdate]);
|
|
|
|
// Subscribe to addon events to refresh catalogs when addons change
|
|
useEffect(() => {
|
|
// Handler for addon order changes
|
|
const handleAddonOrderChange = () => {
|
|
logger.info('Addon order changed, refreshing catalogs');
|
|
loadCatalogs();
|
|
};
|
|
|
|
// Handler for addon added/removed
|
|
const handleAddonChange = () => {
|
|
logger.info('Addon added or removed, refreshing catalogs');
|
|
loadCatalogs();
|
|
};
|
|
|
|
// Subscribe to addon events
|
|
addonEmitter.on(ADDON_EVENTS.ORDER_CHANGED, handleAddonOrderChange);
|
|
addonEmitter.on(ADDON_EVENTS.ADDON_ADDED, handleAddonChange);
|
|
addonEmitter.on(ADDON_EVENTS.ADDON_REMOVED, handleAddonChange);
|
|
|
|
// Cleanup on unmount
|
|
return () => {
|
|
addonEmitter.off(ADDON_EVENTS.ORDER_CHANGED, handleAddonOrderChange);
|
|
addonEmitter.off(ADDON_EVENTS.ADDON_ADDED, handleAddonChange);
|
|
addonEmitter.off(ADDON_EVENTS.ADDON_REMOVED, handleAddonChange);
|
|
};
|
|
}, [loadCatalogs]);
|
|
|
|
// Cleanup on unmount
|
|
useEffect(() => {
|
|
return () => {
|
|
cleanup();
|
|
};
|
|
}, [cleanup]);
|
|
|
|
const refreshCatalogs = useCallback(() => {
|
|
return loadCatalogs(true);
|
|
}, [loadCatalogs]);
|
|
|
|
return { catalogs, loading, refreshing, refreshCatalogs };
|
|
}
|