From f296db8297c7636266cb9b5374285eca4a79de0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A5=D0=B0=D0=BB=D0=B8=D0=BC=D0=BE=D0=B2=20=D0=A0=D1=83?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BC?= Date: Sat, 27 Dec 2025 19:15:22 +0300 Subject: [PATCH] Fix copy link --- src/components/PreviewStep.tsx | 71 ++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 17 deletions(-) diff --git a/src/components/PreviewStep.tsx b/src/components/PreviewStep.tsx index 030e255..ce131f4 100644 --- a/src/components/PreviewStep.tsx +++ b/src/components/PreviewStep.tsx @@ -5,10 +5,10 @@ import * as THREE from 'three'; import JSZip from 'jszip'; import { AppConfig, GeneratedPart, LayoutSplits } from '../types'; import { createBinGeometry, generateSTL, exportSTL } from '../services/geometryGenerator'; -import { Download, Package, Info, Loader2, Share2, Check, Ruler } from 'lucide-react'; -import { generateShareUrl } from '../utils/share'; // <--- Импорт утилиты +import { Download, Package, Info, Loader2, Share2, Check, Ruler, Copy } from 'lucide-react'; +import { generateShareUrl } from '../utils/share'; -// ... (DrawerFrame и BinMesh остаются без изменений) ... +// --- DrawerFrame (Каркас) --- const DrawerFrame = ({ config }: { config: AppConfig }) => { const { width, depth, height } = config.drawer; const offset = 0.5; @@ -22,6 +22,7 @@ const DrawerFrame = ({ config }: { config: AppConfig }) => { ) } +// --- BinMesh (Ячейка) --- interface BinMeshProps { part: GeneratedPart; thickness: number; @@ -49,12 +50,11 @@ const BinMesh: React.FC = ({ part, thickness, isSelected, onClick ); }; -// --- Основной компонент --- - +// --- PreviewStep (Основной) --- interface Props { parts: GeneratedPart[]; config: AppConfig; - splits: LayoutSplits; // <--- Добавили splits в пропсы + splits: LayoutSplits; } export const PreviewStep: React.FC = ({ parts, config, splits }) => { @@ -100,18 +100,55 @@ export const PreviewStep: React.FC = ({ parts, config, splits }) => { } }; - // Логика кнопки "Поделиться" - const handleShare = () => { + // --- Улучшенная функция копирования --- + const handleShare = async () => { const url = generateShareUrl(config, splits); - navigator.clipboard.writeText(url).then(() => { + let success = false; + + try { + // 1. Пробуем современный API (работает только на HTTPS или localhost) + if (navigator.clipboard && navigator.clipboard.writeText) { + await navigator.clipboard.writeText(url); + success = true; + } else { + throw new Error('Clipboard API unavailable'); + } + } catch (err) { + // 2. Если не вышло (например, HTTP), используем Fallback метод + try { + const textArea = document.createElement("textarea"); + textArea.value = url; + + // Делаем элемент невидимым, но частью DOM + textArea.style.position = "fixed"; + textArea.style.left = "-9999px"; + textArea.style.top = "0"; + document.body.appendChild(textArea); + + textArea.focus(); + textArea.select(); + + const result = document.execCommand('copy'); + document.body.removeChild(textArea); + + if (result) success = true; + } catch (e) { + console.error("Copy failed", e); + } + } + + if (success) { setShareUrlCopied(true); - setTimeout(() => setShareUrlCopied(false), 2000); - }); + setTimeout(() => setShareUrlCopied(false), 3000); + } else { + // 3. Если совсем ничего не помогло, показываем промпт + prompt("Не удалось скопировать автоматически. Скопируйте ссылку вручную:", url); + } }; return (
- {/* 1. ВЕРХНЯЯ ПАНЕЛЬ С РАЗМЕРАМИ И КНОПКОЙ SHARE */} + {/* Верхняя панель: Размеры + Поделиться */}
@@ -136,15 +173,15 @@ export const PreviewStep: React.FC = ({ parts, config, splits }) => {