Update social sharing buttons to use popup windows for a more reliable user experience. Adjust Facebook sharer URL format and ensure optimal OG image delivery by defaulting to JPG format and setting cache headers. Update image URLs in gallery data. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 1f7e7e89-a520-4970-9645-37daadc466dc Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 4a846f8c-2e0e-44e4-bcf6-7ac503fb3b19 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/1f7e7e89-a520-4970-9645-37daadc466dc/ZApZ5Qi Replit-Helium-Checkpoint-Created: true
143 lines
4.9 KiB
TypeScript
143 lines
4.9 KiB
TypeScript
import { SiFacebook, SiLinkedin, SiX, SiWhatsapp, SiTelegram, SiPinterest } from "react-icons/si";
|
|
import { Mail, Link2, Check } from "lucide-react";
|
|
import { useState } from "react";
|
|
|
|
interface ShareButtonsProps {
|
|
url: string;
|
|
title: string;
|
|
image?: string;
|
|
}
|
|
|
|
const CANONICAL_DOMAIN = "https://www.folx.tv";
|
|
|
|
function canonicalUrl(url: string): string {
|
|
try {
|
|
const parsed = new URL(url);
|
|
return `${CANONICAL_DOMAIN}${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
} catch {
|
|
return url;
|
|
}
|
|
}
|
|
|
|
function openPopup(shareUrl: string) {
|
|
const w = 600;
|
|
const h = 500;
|
|
const left = window.screenX + (window.outerWidth - w) / 2;
|
|
const top = window.screenY + (window.outerHeight - h) / 2;
|
|
window.open(shareUrl, "share", `width=${w},height=${h},left=${left},top=${top},toolbar=no,menubar=no,scrollbars=yes`);
|
|
}
|
|
|
|
interface ShareTarget {
|
|
name: string;
|
|
icon: typeof SiFacebook;
|
|
color: string;
|
|
getUrl: (url: string, title: string, image?: string) => string;
|
|
popup?: boolean;
|
|
}
|
|
|
|
const SHARE_TARGETS: ShareTarget[] = [
|
|
{
|
|
name: "Facebook",
|
|
icon: SiFacebook,
|
|
color: "hover:bg-[#1877F2] hover:text-white",
|
|
getUrl: (url: string) => `https://www.facebook.com/sharer.php?u=${encodeURIComponent(url)}`,
|
|
popup: true,
|
|
},
|
|
{
|
|
name: "X",
|
|
icon: SiX,
|
|
color: "hover:bg-[#000] hover:text-white",
|
|
getUrl: (url: string, title: string) => `https://x.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`,
|
|
popup: true,
|
|
},
|
|
{
|
|
name: "LinkedIn",
|
|
icon: SiLinkedin,
|
|
color: "hover:bg-[#0A66C2] hover:text-white",
|
|
getUrl: (url: string) => `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`,
|
|
popup: true,
|
|
},
|
|
{
|
|
name: "WhatsApp",
|
|
icon: SiWhatsapp,
|
|
color: "hover:bg-[#25D366] hover:text-white",
|
|
getUrl: (url: string, title: string) => `https://wa.me/?text=${encodeURIComponent(title + " " + url)}`,
|
|
},
|
|
{
|
|
name: "Telegram",
|
|
icon: SiTelegram,
|
|
color: "hover:bg-[#26A5E4] hover:text-white",
|
|
getUrl: (url: string, title: string) => `https://t.me/share/url?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`,
|
|
},
|
|
{
|
|
name: "Pinterest",
|
|
icon: SiPinterest,
|
|
color: "hover:bg-[#BD081C] hover:text-white",
|
|
getUrl: (url: string, title: string, image?: string) => `https://pinterest.com/pin/create/button/?url=${encodeURIComponent(url)}&description=${encodeURIComponent(title)}${image ? "&media=" + encodeURIComponent(image) : ""}`,
|
|
popup: true,
|
|
},
|
|
{
|
|
name: "E-Mail",
|
|
icon: Mail,
|
|
color: "hover:bg-muted-foreground hover:text-white",
|
|
getUrl: (url: string, title: string) => `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(title + "\n\n" + url)}`,
|
|
},
|
|
];
|
|
|
|
export default function ShareButtons({ url, title, image }: ShareButtonsProps) {
|
|
const [copied, setCopied] = useState(false);
|
|
|
|
const handleCopy = async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(canonicalUrl(url));
|
|
setCopied(true);
|
|
setTimeout(() => setCopied(false), 2000);
|
|
} catch {
|
|
const input = document.createElement("input");
|
|
input.value = canonicalUrl(url);
|
|
document.body.appendChild(input);
|
|
input.select();
|
|
document.execCommand("copy");
|
|
document.body.removeChild(input);
|
|
setCopied(true);
|
|
setTimeout(() => setCopied(false), 2000);
|
|
}
|
|
};
|
|
|
|
const handleShare = (target: ShareTarget, e: React.MouseEvent) => {
|
|
const shareUrl = target.getUrl(canonicalUrl(url), title, image ? canonicalUrl(image) : undefined);
|
|
if (target.popup) {
|
|
e.preventDefault();
|
|
openPopup(shareUrl);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-wrap items-center gap-2" data-testid="share-buttons">
|
|
<span className="text-sm text-muted-foreground mr-1">Teilen:</span>
|
|
{SHARE_TARGETS.map((target) => (
|
|
<a
|
|
key={target.name}
|
|
href={target.getUrl(canonicalUrl(url), title, image ? canonicalUrl(image) : undefined)}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
onClick={(e) => handleShare(target, e)}
|
|
className={`inline-flex items-center justify-center w-9 h-9 rounded-full border border-border text-muted-foreground transition-all duration-200 ${target.color}`}
|
|
aria-label={`Auf ${target.name} teilen`}
|
|
data-testid={`button-share-${target.name.toLowerCase()}`}
|
|
>
|
|
<target.icon className="w-4 h-4" />
|
|
</a>
|
|
))}
|
|
<button
|
|
onClick={handleCopy}
|
|
className={`inline-flex items-center justify-center w-9 h-9 rounded-full border border-border transition-all duration-200 ${copied ? "bg-green-600 text-white border-green-600" : "text-muted-foreground hover:bg-muted-foreground hover:text-white"}`}
|
|
aria-label="Link kopieren"
|
|
data-testid="button-share-copy"
|
|
>
|
|
{copied ? <Check className="w-4 h-4" /> : <Link2 className="w-4 h-4" />}
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|