mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-23 02:35:14 +00:00
Enhancement: Add copy link functionality to SeriesModal and VODModal, allowing users to easily copy episode and VOD links to clipboard with notifications for success or failure.
This commit is contained in:
parent
2514528337
commit
0700cf29ea
2 changed files with 99 additions and 18 deletions
|
|
@ -17,7 +17,9 @@ import {
|
|||
Table,
|
||||
Divider,
|
||||
} from '@mantine/core';
|
||||
import { Play } from 'lucide-react';
|
||||
import { Play, Copy } from 'lucide-react';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { copyToClipboard } from '../utils';
|
||||
import useVODStore from '../store/useVODStore';
|
||||
import useVideoStore from '../store/useVideoStore';
|
||||
import useSettingsStore from '../store/settings';
|
||||
|
|
@ -262,6 +264,39 @@ const SeriesModal = ({ series, opened, onClose }) => {
|
|||
showVideo(streamUrl, 'vod', episode);
|
||||
};
|
||||
|
||||
const getEpisodeStreamUrl = (episode) => {
|
||||
let streamUrl = `/proxy/vod/episode/${episode.uuid}`;
|
||||
|
||||
// Add selected provider as query parameter if available
|
||||
if (selectedProvider) {
|
||||
// Use stream_id for most specific selection, fallback to account_id
|
||||
if (selectedProvider.stream_id) {
|
||||
streamUrl += `?stream_id=${encodeURIComponent(selectedProvider.stream_id)}`;
|
||||
} else {
|
||||
streamUrl += `?m3u_account_id=${selectedProvider.m3u_account.id}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (env_mode === 'dev') {
|
||||
streamUrl = `${window.location.protocol}//${window.location.hostname}:5656${streamUrl}`;
|
||||
} else {
|
||||
streamUrl = `${window.location.origin}${streamUrl}`;
|
||||
}
|
||||
return streamUrl;
|
||||
};
|
||||
|
||||
const handleCopyEpisodeLink = async (episode) => {
|
||||
const streamUrl = getEpisodeStreamUrl(episode);
|
||||
const success = await copyToClipboard(streamUrl);
|
||||
notifications.show({
|
||||
title: success ? 'Link Copied!' : 'Copy Failed',
|
||||
message: success
|
||||
? 'Episode link copied to clipboard'
|
||||
: 'Failed to copy link to clipboard',
|
||||
color: success ? 'green' : 'red',
|
||||
});
|
||||
};
|
||||
|
||||
const handleEpisodeRowClick = (episode) => {
|
||||
setExpandedEpisode(expandedEpisode === episode.id ? null : episode.id);
|
||||
};
|
||||
|
|
@ -611,20 +646,34 @@ const SeriesModal = ({ series, opened, onClose }) => {
|
|||
</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<ActionIcon
|
||||
variant="filled"
|
||||
color="blue"
|
||||
size="sm"
|
||||
disabled={
|
||||
providers.length > 0 && !selectedProvider
|
||||
}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePlayEpisode(episode);
|
||||
}}
|
||||
>
|
||||
<Play size={12} />
|
||||
</ActionIcon>
|
||||
<Group spacing="xs">
|
||||
<ActionIcon
|
||||
variant="filled"
|
||||
color="blue"
|
||||
size="sm"
|
||||
disabled={
|
||||
providers.length > 0 &&
|
||||
!selectedProvider
|
||||
}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePlayEpisode(episode);
|
||||
}}
|
||||
>
|
||||
<Play size={12} />
|
||||
</ActionIcon>
|
||||
<ActionIcon
|
||||
variant="outline"
|
||||
color="gray"
|
||||
size="sm"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleCopyEpisodeLink(episode);
|
||||
}}
|
||||
>
|
||||
<Copy size={12} />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
{expandedEpisode === episode.id && (
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ import {
|
|||
Stack,
|
||||
Modal,
|
||||
} from '@mantine/core';
|
||||
import { Play } from 'lucide-react';
|
||||
import { Play, Copy } from 'lucide-react';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { copyToClipboard } from '../utils';
|
||||
import useVODStore from '../store/useVODStore';
|
||||
import useVideoStore from '../store/useVideoStore';
|
||||
import useSettingsStore from '../store/settings';
|
||||
|
|
@ -232,9 +234,9 @@ const VODModal = ({ vod, opened, onClose }) => {
|
|||
}
|
||||
}, [opened]);
|
||||
|
||||
const handlePlayVOD = () => {
|
||||
const getStreamUrl = () => {
|
||||
const vodToPlay = detailedVOD || vod;
|
||||
if (!vodToPlay) return;
|
||||
if (!vodToPlay) return null;
|
||||
|
||||
let streamUrl = `/proxy/vod/movie/${vod.uuid}`;
|
||||
|
||||
|
|
@ -253,9 +255,29 @@ const VODModal = ({ vod, opened, onClose }) => {
|
|||
} else {
|
||||
streamUrl = `${window.location.origin}${streamUrl}`;
|
||||
}
|
||||
return streamUrl;
|
||||
};
|
||||
|
||||
const handlePlayVOD = () => {
|
||||
const streamUrl = getStreamUrl();
|
||||
if (!streamUrl) return;
|
||||
const vodToPlay = detailedVOD || vod;
|
||||
showVideo(streamUrl, 'vod', vodToPlay);
|
||||
};
|
||||
|
||||
const handleCopyLink = async () => {
|
||||
const streamUrl = getStreamUrl();
|
||||
if (!streamUrl) return;
|
||||
const success = await copyToClipboard(streamUrl);
|
||||
notifications.show({
|
||||
title: success ? 'Link Copied!' : 'Copy Failed',
|
||||
message: success
|
||||
? 'Stream link copied to clipboard'
|
||||
: 'Failed to copy link to clipboard',
|
||||
color: success ? 'green' : 'red',
|
||||
});
|
||||
};
|
||||
|
||||
// Helper to get embeddable YouTube URL
|
||||
const getEmbedUrl = (url) => {
|
||||
if (!url) return '';
|
||||
|
|
@ -486,6 +508,16 @@ const VODModal = ({ vod, opened, onClose }) => {
|
|||
Watch Trailer
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
leftSection={<Copy size={16} />}
|
||||
variant="outline"
|
||||
color="gray"
|
||||
size="sm"
|
||||
onClick={handleCopyLink}
|
||||
style={{ alignSelf: 'flex-start' }}
|
||||
>
|
||||
Copy Link
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Flex>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue