mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-18 00:55:50 +00:00
refactor(frontend): extract useEpgPreview to its own hook file
This commit is contained in:
parent
2cfea1df0f
commit
9903f0b75d
4 changed files with 74 additions and 74 deletions
|
|
@ -4,7 +4,6 @@ import ProgramPreview from '../ProgramPreview';
|
|||
|
||||
// Mock Mantine components as lightweight stubs
|
||||
vi.mock('@mantine/core', () => {
|
||||
const React = require('react');
|
||||
return {
|
||||
ActionIcon: ({ children, onClick, ...props }) => (
|
||||
<button onClick={onClick} {...props}>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import useStreamProfilesStore from '../../store/streamProfiles';
|
|||
import ChannelGroupForm from './ChannelGroup';
|
||||
import logo from '../../images/logo.png';
|
||||
import { useChannelLogoSelection } from '../../hooks/useSmartLogos';
|
||||
import { useEpgPreview } from '../../hooks/useEpgPreview';
|
||||
import useLogosStore from '../../store/logos';
|
||||
import LazyLogo from '../LazyLogo';
|
||||
import LogoForm from './Logo';
|
||||
|
|
@ -92,78 +93,6 @@ const ProviderHintRow = ({ channel, field, formValue, hintText, onReset }) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const useEpgPreview = (epgDataId) => {
|
||||
const [currentProgram, setCurrentProgram] = useState(null);
|
||||
const [isLoadingProgram, setIsLoadingProgram] = useState(false);
|
||||
const [hasFetchedProgram, setHasFetchedProgram] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!epgDataId || epgDataId === '0' || epgDataId === '') {
|
||||
setCurrentProgram(null);
|
||||
setIsLoadingProgram(false);
|
||||
setHasFetchedProgram(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
setIsLoadingProgram(true);
|
||||
setHasFetchedProgram(false);
|
||||
|
||||
const fetchWithRetry = async () => {
|
||||
const maxRetries = 5;
|
||||
const deadlineMs = 3 * 60 * 1000; // 3 minutes
|
||||
const startTime = Date.now();
|
||||
let delay = 3000; // 3s initial
|
||||
|
||||
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
||||
if (cancelled || Date.now() - startTime > deadlineMs) break;
|
||||
|
||||
try {
|
||||
const program = await API.getCurrentProgramForEpg(epgDataId);
|
||||
if (cancelled) return;
|
||||
|
||||
if (program && program.parsing && attempt < maxRetries) {
|
||||
// Index still building, retry with backoff
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
delay = Math.min(delay * 1.5, 15000); // 1.5x multiplier, 15s cap
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cancelled) {
|
||||
setCurrentProgram(program && !program.parsing ? program : null);
|
||||
setIsLoadingProgram(false);
|
||||
setHasFetchedProgram(true);
|
||||
}
|
||||
return;
|
||||
} catch (error) {
|
||||
if (!cancelled) {
|
||||
console.error('Failed to fetch current program:', error);
|
||||
}
|
||||
if (attempt < maxRetries) {
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
delay = Math.min(delay * 1.5, 15000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Exhausted retries or deadline
|
||||
if (!cancelled) {
|
||||
setCurrentProgram(null);
|
||||
setIsLoadingProgram(false);
|
||||
setHasFetchedProgram(true);
|
||||
}
|
||||
};
|
||||
|
||||
fetchWithRetry();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [epgDataId]);
|
||||
|
||||
return { currentProgram, isLoadingProgram, hasFetchedProgram };
|
||||
};
|
||||
|
||||
const ChannelForm = ({ channel: channelProp = null, isOpen, onClose }) => {
|
||||
const theme = useMantineTheme();
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ vi.mock('../../../api', () => ({
|
|||
}));
|
||||
|
||||
import API from '../../../api';
|
||||
import { useEpgPreview } from '../Channel';
|
||||
import { useEpgPreview } from '../../../hooks/useEpgPreview';
|
||||
|
||||
describe('Channel EPG preview hook', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
72
frontend/src/hooks/useEpgPreview.jsx
Normal file
72
frontend/src/hooks/useEpgPreview.jsx
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import API from '../api';
|
||||
|
||||
export const useEpgPreview = (epgDataId) => {
|
||||
const [currentProgram, setCurrentProgram] = useState(null);
|
||||
const [isLoadingProgram, setIsLoadingProgram] = useState(false);
|
||||
const [hasFetchedProgram, setHasFetchedProgram] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!epgDataId || epgDataId === '0' || epgDataId === '') {
|
||||
setCurrentProgram(null);
|
||||
setIsLoadingProgram(false);
|
||||
setHasFetchedProgram(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
setIsLoadingProgram(true);
|
||||
setHasFetchedProgram(false);
|
||||
|
||||
const fetchWithRetry = async () => {
|
||||
const maxRetries = 5;
|
||||
const deadlineMs = 3 * 60 * 1000;
|
||||
const startTime = Date.now();
|
||||
let delay = 3000;
|
||||
|
||||
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
||||
if (cancelled || Date.now() - startTime > deadlineMs) break;
|
||||
|
||||
try {
|
||||
const program = await API.getCurrentProgramForEpg(epgDataId);
|
||||
if (cancelled) return;
|
||||
|
||||
if (program && program.parsing && attempt < maxRetries) {
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
delay = Math.min(delay * 1.5, 15000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cancelled) {
|
||||
setCurrentProgram(program && !program.parsing ? program : null);
|
||||
setIsLoadingProgram(false);
|
||||
setHasFetchedProgram(true);
|
||||
}
|
||||
return;
|
||||
} catch (error) {
|
||||
if (!cancelled) {
|
||||
console.error('Failed to fetch current program:', error);
|
||||
}
|
||||
if (attempt < maxRetries) {
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
delay = Math.min(delay * 1.5, 15000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cancelled) {
|
||||
setCurrentProgram(null);
|
||||
setIsLoadingProgram(false);
|
||||
setHasFetchedProgram(true);
|
||||
}
|
||||
};
|
||||
|
||||
fetchWithRetry();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [epgDataId]);
|
||||
|
||||
return { currentProgram, isLoadingProgram, hasFetchedProgram };
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue