({ startDate, endDate })
| 91 | import ErrorBoundary from '../components/ErrorBoundary.jsx'; |
| 92 | |
| 93 | export default function TVChannelGuide({ startDate, endDate }) { |
| 94 | const [isChannelsLoading, setIsChannelsLoading] = useState(false); |
| 95 | const [allowAllGroups, setAllowAllGroups] = useState(true); |
| 96 | const MAX_ALL_CHANNELS = 99999; |
| 97 | |
| 98 | const recordings = useChannelsStore((s) => s.recordings); |
| 99 | const channelGroups = useChannelsStore((s) => s.channelGroups); |
| 100 | const profiles = useChannelsStore((s) => s.profiles); |
| 101 | const [isProgramsLoading, setIsProgramsLoading] = useState(true); |
| 102 | const logos = useLogosStore((s) => s.logos); |
| 103 | |
| 104 | const tvgsById = useEPGsStore((s) => s.tvgsById); |
| 105 | const epgs = useEPGsStore((s) => s.epgs); |
| 106 | |
| 107 | const [programs, setPrograms] = useState([]); |
| 108 | const [guideChannels, setGuideChannels] = useState([]); |
| 109 | const [now, setNow] = useState(getNow()); |
| 110 | const [selectedProgram, setSelectedProgram] = useState(null); |
| 111 | const [selectedChannel, setSelectedChannel] = useState(null); |
| 112 | const [recordingForProgram, setRecordingForProgram] = useState(null); |
| 113 | const [recordChoiceOpen, setRecordChoiceOpen] = useState(false); |
| 114 | const [recordChoiceProgram, setRecordChoiceProgram] = useState(null); |
| 115 | const [recordChoiceChannel, setRecordChoiceChannel] = useState(null); |
| 116 | const [existingRuleMode, setExistingRuleMode] = useState(null); |
| 117 | const [existingRule, setExistingRule] = useState(null); |
| 118 | const [rulesOpen, setRulesOpen] = useState(false); |
| 119 | const [rules, setRules] = useState([]); |
| 120 | const [initialScrollComplete, setInitialScrollComplete] = useState(false); |
| 121 | |
| 122 | // New filter states |
| 123 | const [searchQuery, setSearchQuery] = useState(''); |
| 124 | const [selectedGroupId, setSelectedGroupId] = useState('all'); |
| 125 | const [selectedProfileId, setSelectedProfileId] = useState('all'); |
| 126 | |
| 127 | const env_mode = useSettingsStore((s) => s.environment.env_mode); |
| 128 | |
| 129 | const guideRef = useRef(null); |
| 130 | const timelineRef = useRef(null); // New ref for timeline scrolling |
| 131 | const listRef = useRef(null); |
| 132 | const tvGuideRef = useRef(null); // Ref for the main tv-guide wrapper |
| 133 | const isSyncingScroll = useRef(false); |
| 134 | const guideScrollLeftRef = useRef(0); |
| 135 | const nowLineRef = useRef(null); |
| 136 | const [settledScrollLeft, setSettledScrollLeft] = useState(0); |
| 137 | const scrollDebounceRef = useRef(null); |
| 138 | const { |
| 139 | ref: guideContainerRef, |
| 140 | width: guideWidth, |
| 141 | height: guideHeight, |
| 142 | } = useElementSize(); |
| 143 | |
| 144 | // Decide if 'All Channel Groups' should be enabled (based on total channel count) |
| 145 | useEffect(() => { |
| 146 | let cancelled = false; |
| 147 | (async () => { |
| 148 | try { |
| 149 | const params = new URLSearchParams(); |
| 150 | const ids = await API.getAllChannelIds(params); |
nothing calls this directly
no test coverage detected