diff --git a/web/src/routes/CameraMap.jsx b/web/src/routes/CameraMap.jsx index ca77ec56e..06b556dfe 100644 --- a/web/src/routes/CameraMap.jsx +++ b/web/src/routes/CameraMap.jsx @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { h } from 'preact'; import Card from '../components/Card.jsx'; import Button from '../components/Button.jsx'; @@ -95,11 +96,36 @@ export default function CameraMasks({ camera }) { [motionMaskPoints, setMotionMaskPoints] ); - const handleCopyMotionMasks = useCallback(async () => { - await window.navigator.clipboard.writeText(` motion: - mask: -${motionMaskPoints.map((mask) => ` - ${polylinePointsToPolyline(mask)}`).join('\n')}`); + const handleCopyMotionMasks = useCallback(() => { + const textToCopy = ` motion: + mask: + ${motionMaskPoints.map((mask) => ` - ${polylinePointsToPolyline(mask)}`).join('\n')}`; + + if (window.navigator.clipboard && window.navigator.clipboard.writeText) { + // Use Clipboard API if available + window.navigator.clipboard.writeText(textToCopy).catch((err) => { + console.error('Failed to copy text: ', err); + }); + } else { + // Fallback to document.execCommand('copy') + const textarea = document.createElement('textarea'); + textarea.value = textToCopy; + document.body.appendChild(textarea); + textarea.select(); + + try { + const successful = document.execCommand('copy'); + if (!successful) { + throw new Error('Failed to copy text'); + } + } catch (err) { + console.error('Failed to copy text: ', err); + } + + document.body.removeChild(textarea); + } }, [motionMaskPoints]); + // Zone methods const handleEditZone = useCallback( @@ -127,14 +153,36 @@ ${motionMaskPoints.map((mask) => ` - ${polylinePointsToPolyline(mask)}`).jo ); const handleCopyZones = useCallback(async () => { - await window.navigator.clipboard.writeText(` zones: + const textToCopy = ` zones: ${Object.keys(zonePoints) .map( (zoneName) => ` ${zoneName}: - coordinates: ${polylinePointsToPolyline(zonePoints[zoneName])}` - ) - .join('\n')}`); - }, [zonePoints]); + coordinates: ${polylinePointsToPolyline(zonePoints[zoneName])}`).join('\n')}`; + + if (window.navigator.clipboard && window.navigator.clipboard.writeText) { + // Use Clipboard API if available + window.navigator.clipboard.writeText(textToCopy).catch((err) => { + console.error('Failed to copy text: ', err); + }); + } else { + // Fallback to document.execCommand('copy') + const textarea = document.createElement('textarea'); + textarea.value = textToCopy; + document.body.appendChild(textarea); + textarea.select(); + + try { + const successful = document.execCommand('copy'); + if (!successful) { + throw new Error('Failed to copy text'); + } + } catch (err) { + console.error('Failed to copy text: ', err); + } + + document.body.removeChild(textarea); + } + }, [objectMaskPoints]); // Object methods const handleEditObjectMask = useCallback(