diff --git a/frontend/src/components/tables/ChannelsTable.jsx b/frontend/src/components/tables/ChannelsTable.jsx
index 3bf71d00..21a04bcb 100644
--- a/frontend/src/components/tables/ChannelsTable.jsx
+++ b/frontend/src/components/tables/ChannelsTable.jsx
@@ -41,6 +41,9 @@ import {
Pagination,
NativeSelect,
UnstyledButton,
+ Stack,
+ Select,
+ NumberInput,
} from '@mantine/core';
import { getCoreRowModel, flexRender } from '@tanstack/react-table';
import './table.css';
@@ -211,7 +214,7 @@ const ChannelRowActions = React.memo(
}
);
-const ChannelsTable = ({}) => {
+const ChannelsTable = ({ }) => {
const theme = useMantineTheme();
/**
@@ -283,14 +286,25 @@ const ChannelsTable = ({}) => {
const [isLoading, setIsLoading] = useState(true);
const [hdhrUrl, setHDHRUrl] = useState(hdhrUrlBase);
- const [epgUrl, setEPGUrl] = useState(epgUrlBase);
- const [m3uUrl, setM3UUrl] = useState(m3uUrlBase);
+ const [epgUrl, setEPGUrl] = useState(epgUrlBase); const [m3uUrl, setM3UUrl] = useState(m3uUrlBase);
const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);
const [deleteTarget, setDeleteTarget] = useState(null);
const [isBulkDelete, setIsBulkDelete] = useState(false);
const [channelToDelete, setChannelToDelete] = useState(null);
+ // M3U and EPG URL configuration state
+ const [m3uParams, setM3uParams] = useState({
+ cachedlogos: true,
+ direct: false,
+ tvg_id_source: 'channel_number'
+ });
+ const [epgParams, setEpgParams] = useState({
+ cachedlogos: true,
+ tvg_id_source: 'channel_number',
+ days: 0
+ });
+
/**
* Dereived variables
*/
@@ -514,16 +528,47 @@ const ChannelsTable = ({}) => {
}
}
};
+ // Build URLs with parameters
+ const buildM3UUrl = () => {
+ const params = new URLSearchParams();
+ if (!m3uParams.cachedlogos) params.append('cachedlogos', 'false');
+ if (m3uParams.direct) params.append('direct', 'true');
+ if (m3uParams.tvg_id_source !== 'channel_number') params.append('tvg_id_source', m3uParams.tvg_id_source);
+ const baseUrl = m3uUrl;
+ return params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
+ };
+
+ const buildEPGUrl = () => {
+ const params = new URLSearchParams();
+ if (!epgParams.cachedlogos) params.append('cachedlogos', 'false');
+ if (epgParams.tvg_id_source !== 'channel_number') params.append('tvg_id_source', epgParams.tvg_id_source);
+ if (epgParams.days > 0) params.append('days', epgParams.days.toString());
+
+ const baseUrl = epgUrl;
+ return params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
+ };
// Example copy URLs
const copyM3UUrl = () => {
- copyToClipboard(m3uUrl);
+ copyToClipboard(buildM3UUrl());
+ notifications.show({
+ title: 'M3U URL Copied!',
+ message: 'The M3U URL has been copied to your clipboard.',
+ });
};
const copyEPGUrl = () => {
- copyToClipboard(epgUrl);
+ copyToClipboard(buildEPGUrl());
+ notifications.show({
+ title: 'EPG URL Copied!',
+ message: 'The EPG URL has been copied to your clipboard.',
+ });
};
const copyHDHRUrl = () => {
copyToClipboard(hdhrUrl);
+ notifications.show({
+ title: 'HDHR URL Copied!',
+ message: 'The HDHR URL has been copied to your clipboard.',
+ });
};
const onSortingChange = (column) => {
@@ -812,8 +857,8 @@ const ChannelsTable = ({}) => {
return hasStreams
? {} // Default style for channels with streams
: {
- className: 'no-streams-row', // Add a class instead of background color
- };
+ className: 'no-streams-row', // Add a class instead of background color
+ };
},
});
@@ -891,9 +936,7 @@ const ChannelsTable = ({}) => {
-
-
-
+
}
@@ -909,21 +952,67 @@ const ChannelsTable = ({}) => {
-
-
-
-
-
-
-
-
+
+
+
+
+ }
+ />
+ Use cached logos
+ setM3uParams(prev => ({
+ ...prev,
+ cachedlogos: event.target.checked
+ }))}
+ />
+
-
+
+ Direct stream URLs
+ setM3uParams(prev => ({
+ ...prev,
+ direct: event.target.checked
+ }))}
+ />
+
+
+
}
@@ -938,19 +1027,64 @@ const ChannelsTable = ({}) => {
>
EPG
-
-
-
-
-
-
-
-
+
+
+
+
+
+ }
+ />
+ Use cached logos
+ setEpgParams(prev => ({
+ ...prev,
+ cachedlogos: event.target.checked
+ }))}
+ />
+