mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-22 17:48:09 +00:00
Enhancement: Refactored copyToClipboard utility function to include notification handling internally, eliminating duplicate notification code across the frontend. The function now accepts optional parameters for customizing success/failure messages while providing consistent behavior across all copy operations.
Some checks are pending
CI Pipeline / prepare (push) Waiting to run
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Blocked by required conditions
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
CI Pipeline / create-manifest (push) Blocked by required conditions
Build and Push Multi-Arch Docker Image / build-and-push (push) Waiting to run
Frontend Tests / test (push) Waiting to run
Some checks are pending
CI Pipeline / prepare (push) Waiting to run
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Blocked by required conditions
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
CI Pipeline / create-manifest (push) Blocked by required conditions
Build and Push Multi-Arch Docker Image / build-and-push (push) Waiting to run
Frontend Tests / test (push) Waiting to run
This commit is contained in:
parent
e20858b7b5
commit
aa1f627402
7 changed files with 61 additions and 74 deletions
|
|
@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Better auto-generation of request/response schemas
|
||||
- Improved documentation accuracy with serializer introspection
|
||||
- Switched to uv for package management: Migrated from pip to uv (Astral's fast Python package installer) for improved dependency resolution speed and reliability. This includes updates to Docker build processes, installation scripts (debian_install.sh), and project configuration (pyproject.toml) to leverage uv's features like virtual environment management and lockfile generation. - Thanks [@tobimichael96](https://github.com/tobimichael96) for getting it started!
|
||||
- Copy to Clipboard: Refactored `copyToClipboard` utility function to include notification handling internally, eliminating duplicate notification code across the frontend. The function now accepts optional parameters for customizing success/failure messages while providing consistent behavior across all copy operations.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
|||
|
|
@ -287,13 +287,9 @@ const SeriesModal = ({ series, opened, onClose }) => {
|
|||
|
||||
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',
|
||||
await copyToClipboard(streamUrl, {
|
||||
successTitle: 'Link Copied!',
|
||||
successMessage: 'Episode link copied to clipboard',
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -144,16 +144,10 @@ const Sidebar = ({ collapsed, toggleDrawer, drawerWidth, miniDrawerWidth }) => {
|
|||
// No need to fetch them again here - just use the store values
|
||||
|
||||
const copyPublicIP = async () => {
|
||||
const success = await copyToClipboard(environment.public_ip);
|
||||
if (success) {
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'Public IP copied to clipboard',
|
||||
color: 'green',
|
||||
});
|
||||
} else {
|
||||
console.error('Failed to copy public IP to clipboard');
|
||||
}
|
||||
await copyToClipboard(environment.public_ip, {
|
||||
successTitle: 'Success',
|
||||
successMessage: 'Public IP copied to clipboard',
|
||||
});
|
||||
};
|
||||
|
||||
const onLogout = async () => {
|
||||
|
|
|
|||
|
|
@ -268,13 +268,9 @@ const VODModal = ({ vod, opened, onClose }) => {
|
|||
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',
|
||||
await copyToClipboard(streamUrl, {
|
||||
successTitle: 'Link Copied!',
|
||||
successMessage: 'Stream link copied to clipboard',
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -379,13 +379,9 @@ const ChannelStreams = ({ channel, isExpanded }) => {
|
|||
style={{ cursor: 'pointer' }}
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation();
|
||||
const success = await copyToClipboard(stream.url);
|
||||
notifications.show({
|
||||
title: success ? 'URL Copied' : 'Copy Failed',
|
||||
message: success
|
||||
? 'Stream URL copied to clipboard'
|
||||
: 'Failed to copy URL to clipboard',
|
||||
color: success ? 'green' : 'red',
|
||||
await copyToClipboard(stream.url, {
|
||||
successTitle: 'URL Copied',
|
||||
successMessage: 'Stream URL copied to clipboard',
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -727,14 +727,6 @@ const ChannelsTable = ({ onReady }) => {
|
|||
setRecordingModalOpen(false);
|
||||
};
|
||||
|
||||
const handleCopy = async (textToCopy, ref) => {
|
||||
const success = await copyToClipboard(textToCopy);
|
||||
notifications.show({
|
||||
title: success ? 'Copied!' : 'Copy Failed',
|
||||
message: success ? undefined : 'Failed to copy to clipboard',
|
||||
color: success ? 'green' : 'red',
|
||||
});
|
||||
};
|
||||
// Build URLs with parameters
|
||||
const buildM3UUrl = () => {
|
||||
const params = new URLSearchParams();
|
||||
|
|
@ -759,35 +751,23 @@ const ChannelsTable = ({ onReady }) => {
|
|||
};
|
||||
// Example copy URLs
|
||||
const copyM3UUrl = async () => {
|
||||
const success = await copyToClipboard(buildM3UUrl());
|
||||
notifications.show({
|
||||
title: success ? 'M3U URL Copied!' : 'Copy Failed',
|
||||
message: success
|
||||
? 'The M3U URL has been copied to your clipboard.'
|
||||
: 'Failed to copy M3U URL to clipboard',
|
||||
color: success ? 'green' : 'red',
|
||||
await copyToClipboard(buildM3UUrl(), {
|
||||
successTitle: 'M3U URL Copied!',
|
||||
successMessage: 'The M3U URL has been copied to your clipboard.',
|
||||
});
|
||||
};
|
||||
|
||||
const copyEPGUrl = async () => {
|
||||
const success = await copyToClipboard(buildEPGUrl());
|
||||
notifications.show({
|
||||
title: success ? 'EPG URL Copied!' : 'Copy Failed',
|
||||
message: success
|
||||
? 'The EPG URL has been copied to your clipboard.'
|
||||
: 'Failed to copy EPG URL to clipboard',
|
||||
color: success ? 'green' : 'red',
|
||||
await copyToClipboard(buildEPGUrl(), {
|
||||
successTitle: 'EPG URL Copied!',
|
||||
successMessage: 'The EPG URL has been copied to your clipboard.',
|
||||
});
|
||||
};
|
||||
|
||||
const copyHDHRUrl = async () => {
|
||||
const success = await copyToClipboard(hdhrUrl);
|
||||
notifications.show({
|
||||
title: success ? 'HDHR URL Copied!' : 'Copy Failed',
|
||||
message: success
|
||||
? 'The HDHR URL has been copied to your clipboard.'
|
||||
: 'Failed to copy HDHR URL to clipboard',
|
||||
color: success ? 'green' : 'red',
|
||||
await copyToClipboard(hdhrUrl, {
|
||||
successTitle: 'HDHR URL Copied!',
|
||||
successMessage: 'The HDHR URL has been copied to your clipboard.',
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
|
||||
export default {
|
||||
Limiter: (n, list) => {
|
||||
|
|
@ -76,30 +77,53 @@ export function sleep(ms) {
|
|||
export const getDescendantProp = (obj, path) =>
|
||||
path.split('.').reduce((acc, part) => acc && acc[part], obj);
|
||||
|
||||
export const copyToClipboard = async (value) => {
|
||||
export const copyToClipboard = async (value, options = {}) => {
|
||||
const {
|
||||
successTitle = 'Copied!',
|
||||
successMessage = 'Copied to clipboard',
|
||||
failureTitle = 'Copy Failed',
|
||||
failureMessage = 'Failed to copy to clipboard',
|
||||
showNotification = true,
|
||||
} = options;
|
||||
|
||||
let success = false;
|
||||
|
||||
if (navigator.clipboard) {
|
||||
// Modern method, using navigator.clipboard
|
||||
try {
|
||||
await navigator.clipboard.writeText(value);
|
||||
return true;
|
||||
success = true;
|
||||
} catch (err) {
|
||||
console.error('Failed to copy: ', err);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback method for environments without clipboard support
|
||||
try {
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = value;
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
const successful = document.execCommand('copy');
|
||||
document.body.removeChild(textarea);
|
||||
return successful;
|
||||
} catch (err) {
|
||||
console.error('Failed to copy with fallback method: ', err);
|
||||
return false;
|
||||
if (!success) {
|
||||
// Fallback method for environments without clipboard support
|
||||
try {
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = value;
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
const successful = document.execCommand('copy');
|
||||
document.body.removeChild(textarea);
|
||||
success = successful;
|
||||
} catch (err) {
|
||||
console.error('Failed to copy with fallback method: ', err);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Show notification if enabled
|
||||
if (showNotification) {
|
||||
notifications.show({
|
||||
title: success ? successTitle : failureTitle,
|
||||
message: success ? successMessage : failureMessage,
|
||||
color: success ? 'green' : 'red',
|
||||
});
|
||||
}
|
||||
|
||||
return success;
|
||||
};
|
||||
|
||||
export const setCustomProperty = (input, key, value, serialize = false) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue